我想用TweenAnimationBuilder制作一个翻转动画,一个容器会翻转并改变颜色。我想添加一个按钮,当用户点击它时,容器会再次翻转并变成另一种颜色。
这是我的代码:
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool isBack = true;
Color backColor = Colors.green;
Color topColor = Colors.red;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
box(),
SizedBox(height: 10),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: Size(25, 10),
elevation: 10,
),
onPressed: () {
setState(() {
backColor = Colors.red;
topColor = Colors.blue;
});
},
child:
Text('change to blue', style: TextStyle(fontSize: 16))),
],
),
),
),
);
}
Widget box() {
print('building');
return TweenAnimationBuilder(
tween: Tween<double>(begin: 0, end: pi),
duration: Duration(seconds: 1),
builder: (BuildContext context, double value, _) {
print(value);
if (value >= (pi / 2)) {
isBack = false;
} else {
isBack = true;
}
return (Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(value),
child: Container(
width: 100,
height: 100,
child: isBack
? Container(
color: backColor,
)
: Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..rotateY(
pi),
child: Container(
color: topColor,
),
)
),
));
});
}
}
在第一次构建时,补间值将从头开始:
building
0
0
0
0.13080335172486462
0.19619246121668257
0.2180893620122034
...
3.141592653589793
但是当我点击按钮改变颜色时,它不会从开始值重新开始,它只是停留在3.14:
building
3.141592653589793
现在按钮只会改变容器的颜色,但不会再次翻转。
我想在 setstate 函数之后,补间值会再次从 0 重新开始,为什么不会这样做呢? 有人可以解释一下吗?
您只需要一个
AnimationController
和 AnimatedBuilder
来控制动画。
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
bool isBack = true;
Color backColor = Colors.blue;
Color topColor = Colors.red;
late AnimationController _animationController;
late Animation _rotationAnimation;
@override
void initState() {
super.initState();
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 1));
_rotationAnimation =
Tween<double>(begin: 0, end: pi).animate(_animationController);
_animationController.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
box(),
SizedBox(height: 10),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: Size(25, 10),
elevation: 10,
),
onPressed: () {
setState(() {
backColor = Colors.red;
topColor = Colors.blue;
});
// if (_animationController.isDismissed) {
// _animationController.forward();
// } else if (_animationController.isCompleted) {
// _animationController.reverse();
// }
_animationController.forward(from: 0.0);
},
child:
Text('change to blue', style: TextStyle(fontSize: 16))),
],
),
),
),
);
}
Widget box() {
return AnimatedBuilder(
animation: _animationController,
// tween: Tween<double>(begin: 0, end: pi),
// duration: Duration(seconds: 1),
builder: (_, __) {
// print(value);
if (_rotationAnimation.value >= (pi / 2)) {
isBack = false;
} else {
isBack = true;
}
return Transform(
alignment: Alignment.center,
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateY(_rotationAnimation.value),
child: Container(
width: 100,
height: 100,
child: isBack
? Container(
color: backColor,
)
: Transform(
alignment: Alignment.center,
transform: Matrix4.identity()..rotateY(pi),
child: Container(
color: topColor,
),
),
),
);
});
}
}
您只需为 TweenAnimationBuilder 提供一个键即可。
TweenAnimationBuilder<T>(
key: UniqueKey(),
duration: const Duration(milliseconds: 700),
您的情况的原因是:Flutter 没有为新的 TweenAnimationBuilder 小部件创建新元素,这是为了性能。