老孟导读:此篇文章是 Flutter 动画系列文章第三篇,后续还有动画序列、过度动画、转场动画、自定义动画等。 Flutter 系统提供了20多个动画组件,只要你把前面【动画核心】(文末有链接)的文章
- 创建 AnimationController。
- 监听 AnimationController,调用
setState
刷新UI。
- 释放 AnimationController。
class MyAnimatedWidget extends StatefulWidget {
final AnimationController controller;
final Widget child;
const MyAnimatedWidget(
{Key key,@required this.controller,@required this.child})
: super(key: key);
@override
_MyAnimatedWidgetState createState() => _MyAnimatedWidgetState();
}
class _MyAnimatedWidgetState extends State<MyAnimatedWidget> {
@override
void initState() {
super.initState();
widget.controller.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return widget.child;
}
@override
void dispose() {
super.dispose();
widget.controller.dispose();
}
}
- 监听 AnimationController,调用
setState
。
- 释放 AnimationController。
-
-
ValueListenable :扩展[Listenable]接口的接口,具有当前值的概念。
-
Animation:一个扩展[ValueListenable]接口的接口,添加方向(正向或反向)的概念。
-
class AnimationDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() => _AnimationDemo();
}
class _AnimationDemo extends State<AnimationDemo>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
Animation _animation;
@override
void initState() {
_animationController =
AnimationController(duration: Duration(seconds: 2),vsync: this);
_animation = Tween(begin: .5,end: .1).animate(_animationController);
//开始动画
_animationController.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
return ScaleTransition(
scale: _animation,child: Container(
height: 200,width: 200,color: Colors.red,),);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
class AnimatedWidgetDemo extends StatefulWidget {
@override
_AnimatedWidgetDemoState createState() => _AnimatedWidgetDemoState();
}
class _AnimatedWidgetDemoState extends State<AnimatedWidgetDemo> {
double _opacity = 1.0;
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedOpacity(
opacity: _opacity,duration: Duration(seconds: 2),child: GestureDetector(
onTap: () {
setState(() {
_opacity = 0;
});
},child: Container(
height: 60,width: 150,color: Colors.blue,);
}
}
-
隐式动画组件:只需提供给组件动画开始、结束值,组件创建 AnimationController、Curve、Tween,执行动画,释放AnimationController,我们称之为隐式动画组件,隐式动画组件有: AnimatedAlign、AnimatedContainer、AnimatedDefaultTextStyle、AnimatedOpacity、AnimatedPadding、AnimatedPhysicalModel、AnimatedPositioned、AnimatedPositionedDirectional、AnimatedTheme、SliverAnimatedOpacity、TweenAnimationBuilder、AnimatedContainer 等。
-
显示动画组件:需要设置 AnimationController,控制动画的执行,使用显式动画可以完成任何隐式动画的效果,甚至功能更丰富一些,不过你需要管理该动画的 AnimationController 生命周期,AnimationController 并不是一个控件,所以需要将其放在 stateful 控件中。显示动画组件有:AlignTransition、AnimatedBuilder、AnimatedModalBarrier、DecoratedBoxTransition、DefaultTextStyleTransition、PositionedTransition、RelativePositionedTransition、RotationTransition、ScaleTransition、SizeTransition、SlideTransition 、FadeTransition 等。
class AnimatedBuilderDemo extends StatefulWidget {
@override
_AnimatedBuilderDemoState createState() => _AnimatedBuilderDemoState();
}
class _AnimatedBuilderDemoState extends State<AnimatedBuilderDemo>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<Color> _colorAnimation;
Animation<Size> _sizeAnimation;
@override
void initState() {
_controller =
AnimationController(vsync: this,duration: Duration(seconds: 2));
_colorAnimation =
ColorTween(begin: Colors.blue,end: Colors.red).animate(_controller);
_sizeAnimation =
SizeTween(begin: Size(100.0,50.0),end: Size(200.0,100.0))
.animate(_controller);
_controller.forward();
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
animation: _controller,builder: (context,widget) {
return Container(
width: _sizeAnimation.value.width,height: _sizeAnimation.value.height,color: _colorAnimation.value,);
},);
}
}
- 判断你的动画组件是否一直重复,比如一直转圈的loading动画,如果是选择显式动画。
- 判断你的动画组件是否需要多个组件联动,如果是选择显式动画。
- 判断你的动画组件是否需要组合动画,如果是选择显式动画。
- 如果上面三个条件都是否,就选择隐式动画组件,判断是否已经内置动画组件,如果没有,使用 TweenAnimationBuilder,有就直接使用内置动画组件。
- 选择显式动画组件,判断是否已经内置动画组件,如果没有,使用 AnimatedBuilder,有就直接使用内置动画组件。