• flutter 记录学习不一样的动画(二)


    一、AnimatedWidget 简介

    AnimatedWidget 基本类可以从动画代码中区分出核心 widget 代码。 AnimatedWidget 不需要保持 State 对象来 hold 动画。AnimatedWidget 帮助类(代替 addListener() 和 setState())创建动画 widget。
    利用 AnimatedWidget 创建一个可以运行重复使用动画的 widget。
    Flutter API 中的 AnimatedWidget:AnimatedBuilder, RotationTransition, ScaleTransition, SizeTransition, SlideTransition。

    二、AnimatedWidget 动画示例

    一个从矩形的宽高收缩

    class MyAnimationWidget extends StatefulWidget {
      const MyAnimationWidget({Key? key}) : super(key: key);
    
      @override
      _MyAnimationWidgetState createState() => _MyAnimationWidgetState();
    }
    
    class _MyAnimationWidgetState extends State<MyAnimationWidget>
        with SingleTickerProviderStateMixin {
      late AnimationController controller;
      late Animation<double> animation;
    
      @override
      initState() {
        super.initState();
        controller = AnimationController(
            duration: const Duration(milliseconds: 2000), vsync: this);
        animation = Tween(begin: 0.0, end: 300.0).animate(controller);
        controller.forward();
      }
    
      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: AnimationLogo(animation),
          ),
        );
      }
    }
    
    class AnimationLogo extends AnimatedWidget {
     const AnimatedLogo({super.key, required Animation<double> animation})
          : super(listenable: animation);
    
      @override
      Widget build(BuildContext context) {
       final animation = listenable as Animation<double>;
        return Center(
          child: Container(
            height: animation.value,
            width: animation.value,
            color: Colors.red,
          ),
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    三、使用 AnimatedBuilder 进行重构

    AnimatedBuilder 知道如何渲染过渡效果

    但 AnimatedBuilder 不会渲染 widget,也不会控制动画对象。

    使用 AnimatedBuilder 描述一个动画是其他 widget 构建方法的一部分。如果只是单纯需要用可重复使用的动画定义一个 widget。

    Flutter API 中 AnimatedBuilders:BottomSheet, ExpansionTile, PopupMenu, ProgressIndicator, RefreshIndicator, Scaffold, SnackBar, TabBar, TextField。

    AnimatedWidget 示例代码中有个问题,就是改变动画需要改变渲染 logo 的widget。较好的解决办法是,将任务区分到不同类里:

    a. 渲染 logo

    b. 定义动画对象

    c. 渲染过渡效果

    AnimatedBuilder 动画示例

    class _MyAnimationWidgetState extends State<MyAnimationWidget>
        with SingleTickerProviderStateMixin {
      late AnimationController controller;
      late Animation<double> animation;
    
      @override
      initState() {
        super.initState();
        controller = AnimationController(
            duration: const Duration(milliseconds: 2000), vsync: this);
        animation = Tween(begin: 0.0, end: 300.0).animate(controller);
        controller.forward();
      }
    
      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: AnimationLogo(
              animation,
              child: LogoWidget(),
            ),
          ),
        );
      }
    }
    
    class LogoWidget extends StatelessWidget {
      const LogoWidget({Key? key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Container(
            color: Colors.red,
          ),
        );
      }
    }
    
    class AnimationLogo extends StatelessWidget {
      final Animation<double> animation;
      final Widget child;
      AnimationLogo(this.animation, {Key? key, required this.child});
    
      @override
      Widget build(BuildContext context) {
        return AnimatedBuilder(
          animation: animation,
          builder: (BuildContext context, Widget? child) {
            return SizedBox(
              height: animation.value,
              width: animation.value,
              child: child,
            );
          },
          child: child,
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    四、总结

    从上面代码可以看出widget和动画效果分开了,所以AnimatedBuilder进一步将AnimatedWidget 进行分离,这样就可以让动画效果进行复用了,非常不错的。

  • 相关阅读:
    zabbix自动发现和自动注册
    【linux】权限管理 详解(文件/访问者/目录 权限、权限指令、粘滞位... ...)
    echarts 设置legend的样式
    手写RPC框架 第六天 负载均衡
    接口自动化测试 —— 协议、请求流程
    Spring 的注入
    docker compose搭建redis7.0.4高可用一主二从三哨兵集群并整合SpringBoot【图文完整版】
    vue3 antd 表单校验与重置
    使用electron ipcRenderer接收通信消息多次触发
    国家数据局正式揭牌,数据专业融合型人才迎来发展良机
  • 原文地址:https://blog.csdn.net/hjjdehao/article/details/126059714