Flutter 106: 图解 AnimatedWidget & AnimatedBuilder 动画应用

简介: 0 基础学习 Flutter,第一百零六步:学习一下 AnimatedWidget 和 AnimatedBuilder 简单的动画应用!

     小菜继续上一节中自定义的 ACEPageMenu 滑动菜单,详细介绍一下涉及到的 AnimatedBuilder 动画,在此之前需要先了解 AnimatedWidget

AnimatedWidget

     AnimatedWidget 是一个有状态的 StatefulWidget 小部件,通过指定 Listenable 更改值时重建小部件;AnimatedWidget 对于无状态的窗口小部件比较实用;含有众多子类动画,小菜会在之后的博客中慢慢学习;

源码分析

abstract class AnimatedWidget extends StatefulWidget {
  const AnimatedWidget({
    Key key,
    @required this.listenable,
  }) : super(key: key);

  final Listenable listenable;

  @protected
  Widget build(BuildContext context);

  @override
  _AnimatedState createState() => _AnimatedState();

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<Listenable>('animation', listenable));
  }
}

     分析源码可得,AnimatedWidget 主要通过 Listenable 来监听小部件动画,通常是 AnimationChangeNotifier;通过重写 build() 方法来设置动画过程;并在 _AnimatedState 中设置状态的更新 setState()

     由此可见,AnimatedWidget 已封装好 setState() 状态更新模块,允许将调用中的动画代码中分离出 Widget,而无需单独维护一个 State 状态来保存动画;

案例尝试

     小菜尝试 AnimatedWidget 方式展示一个类似 ACEPageMenu 从顶部滑出的一个小动画效果;

class TopMenuWidget extends AnimatedWidget {
  const TopMenuWidget({Key key, AnimationController controller}) : super(key: key, listenable: controller);

  Animation<double> get _progress => listenable;

  @override
  Widget build(BuildContext context) {
    return Transform.translate(
        offset: Offset(50, 100 * _progress.value),
        child: Opacity(
            opacity: _progress.value,
            child: Container(
                width: 300.0, height: 100.0,
                color: Colors.yellow,
                child: Center(
                    child: GestureDetector(
                        onTap: () => print('I am from AnimatedWidget !'),
                        child: Icon(Icons.ac_unit, color: Colors.white))))));
  }
}

AnimatedBuilder

      AnimatedBuilder 也是用于构建动画的通用 Widget,是渲染树中的一个独立的类,适用于要提取单独动画效果的较复杂的 Widget;可自动监听来自 Animation 对象的通知,无需手动调用 addListener()

源码分析

class AnimatedBuilder extends AnimatedWidget {
  const AnimatedBuilder({
    Key key,
    @required Listenable animation,
    @required this.builder,
    this.child,
  }) : super(key: key, listenable: animation);

  final TransitionBuilder builder;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return builder(context, child);
  }
}

typedef TransitionBuilder = Widget Function(BuildContext context, Widget child);

      分析源码可得,AnimatedBuilder 继承自 AnimatedWidget,只需构造窗口小部件并将其传递给构建器函数即可;其中 TransitionBuilder 在每次动画更改值时调用;其中 child 比较特殊,可以作为优化的方向;

      如果 builder 函数包含一个不依赖于动画的子树,则一次构建该子树比在每个动画变更时都重新构建子树更为高效;即在 child 中预先定义好 WidgetAnimatedBuilder 会将其传递到构造器函数中;

案例尝试

     小菜尝试 AnimatedBuilder 方式展示一个类似 ACEPageMenu 从底部滑出的一个小动画效果;

return AnimatedBuilder(
    animation: _controller,
    child: Container(
        color: Colors.brown,
        height: 100.0, width: 300.0,
        child: Center(
            child: GestureDetector(
                onTap: () => print('I am form AnimatedBuilder !'),
                child: Icon(Icons.ac_unit, color: Colors.white)))),
    builder: (BuildContext context, Widget child) {
      return Transform.translate(
          offset: Offset(50, ScreenUtils.getScreenHeight() - _controller.value * 200),
          child: Opacity(opacity: _controller.value, child: child));
    });

     条条大路通罗马,同一效果可以有多种不同的实现方式;AnimatedWidgetAnimatedBuilder 使用都很便利,而小菜认为 AnimatedBuilder 在处理复杂动画时更加灵活方便;

注意事项

      小菜在尝试缩放动画过程中,遇到之前不曾注意的地方,即动画起始位置由 originalignment 共同决定,以 aligment 对齐位置为坐标原点,origin 在此基础上平移起始位置;与 scale 无关;

Transform.scale({
    Key key,
    @required double scale,
    this.origin,
    this.alignment = Alignment.center,
    this.transformHitTests = true,
    Widget child,
})

      小菜尝试了几个基本场景:

  1. alignment 对齐方式默认居中,origin 起始位置默认为 Offset.zero 时,scale 增大为 1.5 倍;可以看到其初始动画位置仍为 Widget 缩放前的中心位;
return Transform.scale(
    scale: _progress.value * 1.5,
    origin: Offset.zero,
    alignment: Alignment.center,
    child: Container(width: 200.0, height: 200.0, color: Colors.yellow.withOpacity(0.8)));

  1. alignment 对齐方式默认居中,调整 origin 起始位置为 Offset(50, 50);可以看到其初始动画位置是以 alignment 居中点为原点,水平竖直方向为坐标系轴,平移 origin 位置;
return Transform.scale(
    scale: _progress.value,
    origin: Offset(50, 50),
    alignment: Alignment.center,
    child: Container(width: 200.0, height: 200.0, color: Colors.yellow.withOpacity(0.8)));

  1. alignment 默认居中右对齐,origin 起始位置为 Offset(50, 50);可以看到其初始动画位置是以 alignment 居中右对齐中点为原点,水平竖直方向为坐标系轴,平移 origin 位置;
return Transform.scale(
    scale: _progress.value,
    origin: Offset(50, 50),
    alignment: Alignment.centerRight,
    child: Container(width: 200.0, height: 200.0, color: Colors.yellow.withOpacity(0.8)));


      AnimatedWidget 和 AnimatedBuilder 案例源码


      小菜对动画的源码还不够深入,如有错误,请多多指导!

来源: 阿策小和尚

目录
相关文章
|
2月前
|
缓存 监控 前端开发
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
【4月更文挑战第30天】本文探讨了Flutter应用启动优化策略,包括理解启动过程、资源加载优化、减少初始化工作、界面布局简化、异步初始化、预加载关键数据、性能监控分析以及案例和未来优化方向。通过这些方法,可以缩短启动时间,提升用户体验。使用Flutter DevTools等工具可助于识别和解决性能瓶颈,实现持续优化。
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
|
2月前
|
Dart 前端开发 开发工具
【Flutter前端技术开发专栏】Flutter入门指南:搭建开发环境与第一个应用
【4月更文挑战第30天】本文介绍了Flutter SDK的安装和配置过程,以及如何创建并运行第一个Flutter应用。首先确保安装了Dart SDK和Flutter SDK,支持macOS、Linux和Windows。安装完成后,设置环境变量,然后通过`flutter doctor`验证安装。接着,使用`flutter create`命令创建新项目,进入项目目录并运行`flutter run`启动应用。在`main.dart`中修改代码以自定义应用。Flutter支持热重载和DevTools调试。本文为Flutter初学者提供了快速入门的指导。
【Flutter前端技术开发专栏】Flutter入门指南:搭建开发环境与第一个应用
|
9天前
|
监控 Serverless 持续交付
阿里云云效产品使用问题之如何让流水线支持构建 flutter web 应用到 OSS
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
15天前
|
缓存 视频直播
flutter3-dylive 基于flutter3.19+getx短视频/直播应用
基于跨端技术flutter3.19+dart3+getx实战短视频/直播应用项目。
27 4
|
26天前
|
Dart 监控 开发者
详细介绍Flutter Profiler的功能、使用方法以及如何利用它来提升应用的性能
【6月更文挑战第11天】Flutter Profiler是用于优化Flutter应用的关键工具,提供CPU、GPU、内存和网络分析。它帮助开发者监控运行时性能,识别瓶颈,如CPU过度使用、渲染问题、内存泄漏和网络效率低。通过选择分析类型、开始分析、查看结果,开发者可进行针对性优化。最佳实践包括定期分析、结合实际场景、关注关键指标及结合其他工具。有效利用Profiler能提升应用性能和用户体验。
41 2
|
4天前
Flutter-实现头像叠加动画效果
Flutter-实现头像叠加动画效果
|
4天前
Flutter-加载中动画
Flutter-加载中动画
|
4天前
Flutter-自定义表情雨下落动画
Flutter-自定义表情雨下落动画
|
4天前
Flutter-数字切换动画
Flutter-数字切换动画
|
4天前
|
开发者
Flutter 动画学习
Flutter 动画学习