Flutter(十五)——动画的封装与简化
前言
在上一篇的动画内容中,我们学习了基本的概念,以及动画的基本使用规则,但是,上一篇的代码真的实际项目中应用很多吗?其实不是,上一篇之所以那么介绍,只是为了让大家更了解Flutter动画的原理,其实还有更简单封装与简化的使用方式,这一篇就开始学习这些内容。
AnimatedWidget
前面动画之中,我们都是通过addListener和setState来更新UI的,然而有时候可以不用这么麻烦,通过AnimationWidget这个类就可以实现,它对addListener和setState进行了封装,隐藏了实现细节。下面,我们直接上代码来看看:
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
Animation<double> animation;
AnimationController controller; initState(){ super.initState(); controller=AnimationController(duration: const Duration(milliseconds: 2000),vsync: this); animation=CurvedAnimation(parent: controller,curve: Curves.bounceIn)..addStatusListener((status){ if(status==AnimationStatus.completed){//动画在结束时停止的状态 controller.reverse();//颠倒 }else if(status==AnimationStatus.dismissed){//动画在开始时就停止的状态 controller.forward();//向前 } })..addListener((){ setState(() { print(animation.value); }); }); controller.forward();
} @override
void dispose() { controller.dispose(); // TODO: implement dispose super.dispose();
} @override
Widget build(BuildContext context) { return AnimationLogo(animation: animation,);
}
}
class AnimationLogo extends AnimatedWidget{ AnimationLogo({Key key,Animation<double> animation}) :super(key:key,listenable:animation); @override
Widget build(BuildContext context) { final Animation<double> animation=listenable; return Scaffold( appBar: AppBar( title: Text("封装动画"), ), body: Container( height: animation.value*300, margin: EdgeInsets.symmetric(vertical: 10.0), width: animation.value*300, child: FlutterLogo(), ), );
}
}
封装后,AnimationLogo可以通过当前自身Animation的value值来绘制自己。
AnimatedBuilder
有时候我们会使用多个AnimatedWidget,而如果多次实现AnimatedWidget,则代码就显得不那么美观了,这个时候,我们就需要考虑使用AnimatedBuilder,它的优点有:
(1)不需要知道如何渲染组件,也不需要知道如何管理动画对象
(2)继承自AnimatedWidget,可以直接当作组件来使用,且不用显式地去添加帧的监听addListener(…),然后在调用setState
(3)只调用动画组件中地build,在复杂地布局下性能有所提高
我们先来看一张组件示意图:
接着我们将上面的代码进行重构,代码如下:
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
Animation<double> animation;
AnimationController controller; initState(){ super.initState(); controller=AnimationController(duration: const Duration(milliseconds: 2000),vsync: this); animation=CurvedAnimation(parent: controller,curve: Curves.bounceIn)..addStatusListener((status){ if(status==AnimationStatus.completed){//动画在结束时停止的状态 controller.reverse();//颠倒 }else if(status==AnimationStatus.dismissed){//动画在开始时就停止的状态 controller.forward();//向前 } })..addListener((){ setState(() { }); }); controller.forward();
} @override
void dispose() { controller.dispose(); // TODO: implement dispose super.dispose();
} @override
Widget build(BuildContext context) { return GrowTransition(child:AnimationLogo(),animation: animation,);
}
}
class AnimationLogo extends StatelessWidget{
@override
Widget build(BuildContext context) { // TODO: implement build return Container( margin: EdgeInsets.symmetric(vertical: 10), child: FlutterLogo(), );
}
}
class GrowTransition extends StatelessWidget{
final Widget child;
final Animation<double> animation;
GrowTransition({this.child,this.animation});
@override
Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("AnimatedBuilder"),), body: Center( child: AnimatedBuilder( animation: this.animation, builder: (BuildContext context,Widget child){ return Container( height: animation.value*300, width: animation.value*300, child: child, ); }, child: this.child, ), ), );
}
}
前面的代码基本一样,就是后面的代码变更了,所以重点看后面的代码就行。其实在Flutter开发中,通过AnimatedBuilder方式还封装了很多动画,比如SizeTransition,ScaleTransition,RotationTransition,FadeTransition,FractionalTranslation等。很多时候我们都可以反复使用这些预置的过渡类。效果图更前篇文章差不多,这里就不展示了。
文章来源: liyuanjinglyj.blog.csdn.net,作者:李元静,版权归原作者所有,如需转载,请联系作者。
原文链接:liyuanjinglyj.blog.csdn.net/article/details/104136939
- 点赞
- 收藏
- 关注作者
评论(0)