Flutter(十五)——动画的封装与简化

简介: 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等。很多时候我们都可以反复使用这些预置的过渡类。效果图更前篇文章差不多,这里就不展示了。

相关文章
|
9月前
|
Android开发 iOS开发 容器
Flutter控件封装之轮播图Banner
Flutter中实现轮播图的方式有很多种,比如使用三方flutter_swiper,card_swiper等等,使用这些三方,可以很快很方便的实现一个轮播图展示,基本上也能满足我们日常的开发需求,如果说,想要一些定制化的操作,那么就不得不去更改源码或者自己自定义一个,自己定义的话,Flutter中提供了原生组件PageView,可以使用它很方便的来实现一个轮播图。
181 0
|
3月前
|
前端开发
Flutter笔记:光影动画按钮、滚动图标卡片组等
Flutter笔记:光影动画按钮、滚动图标卡片组等
40 0
|
4月前
|
UED
Flutter之自定义路由切换动画
Flutter之自定义路由切换动画 在Flutter中,我们可以通过Navigator来实现路由管理,包括路由的跳转和返回等。默认情况下,Flutter提供了一些简单的路由切换动画,但是有时候我们需要自定义一些特殊的动画效果来提高用户体验。本文将介绍如何在Flutter中实现自定义的路由切换动画。
|
4月前
|
开发框架
Flutter 工程化框架选择——搞定 Flutter 动画
Flutter 工程化框架选择——搞定 Flutter 动画 Flutter 是 Google 推出的跨平台移动应用开发框架,它具有快速开发、高性能、美观等优点。但是,在实际开发中,为了更好地维护和扩展代码,我们需要选择一个合适的工程化框架来协助我们进行开发。本文将介绍几种常用的 Flutter 工程化框架,并重点介绍一个搞定 Flutter 动画的方法。
|
9月前
|
API Android开发
Flutter控件封装之视频进度条
视频控制器,三方所提供的样式,有时很难满足我们的需求,对于此情况,我们不得不在此基础上自行封装,今天所分享的文章就是一个很简单的控制器封装案例,包含了基本的播放暂停,全屏和退出全屏,以及时间和进度的展示,封装了事件回调以及各个属性的控制,基本上可以满足大部分的业务需求,即便不满足,大家也可以在此基础之上拓展。
131 0
|
9月前
|
Android开发 UED
Flutter控件之Tab选项卡封装
Tab选项卡,这是一个非常常见且权重很高的一个组件,随便打开一个App,比如掘金,如下图,首页顶部就是一个Tab选项卡,这个功能可以说,几乎每个App都会存在。
169 0
|
9月前
|
存储 Android开发
Flutter控件之图片Image封装
Flutter中偏偏原生的控件,少了很多需要又常用的属性,比如宽高,比如内外边距,又比如点击事件,如果不采取封装,视图的结构会一层嵌套一层,徒增很多的冗余代码,所以,为了简洁代码,还有为了拓展原生组件没有的属性,就不得不进行一次简单的封装,使其在调用的时候,可以很方便的实现某些功能。
|
9月前
|
API
Flutter控件之文本Text封装
文本Text比较简单,除了基类BaseWidget所提供的属性之外,又简单的扩展了部分属性,比如图文和富文本,都是系统原生的提供的,做了简单的封装。
|
9月前
|
API Android开发 容器
Flutter控件之基类Widget封装
基类的Widget主要确定以下几个方面,第一就是,自定义一个抽象类还是非抽象类,第二、继承方式,采取有状态还是无状态,第三、关于组件的点击方式,如何进行实现。
104 0
|
11月前
|
设计模式 算法 vr&ar
Flutter 基础 | 动画框架分析及其中的设计模式
Flutter 基础 | 动画框架分析及其中的设计模式
113 0