Flutter 组件集录 | 隐式动画组件 * 4

ImplicitlyAnimated.png

最近盘点 Flutter 中的内置组件,发现隐式动画(ImplicitlyAnimated) 中没有收录的四个组件,可能是后期版本增加的。本文介绍一下它们的使用,并加入到 FlutterUnit 中。隐式动画可以让使用者 不使用动画控制器,仅通过修改组件属性达到动画效果。下面是本文四个组件的效果展示:

AnimatedSlide

AnimatedRotation

AnimatedScale

AnimatedFractionallySizedBox


1. AnimatedSlide 滑动动画

AnimatedSlide 组件在构造时需要传入 Offset 对象,用于控制偏移量。这个偏移量是 系数,比如 dy 为 2 ,表示需要向上偏移两倍的 自身高度,并且变化过程具有动画效果。

该案例中,红色方框边长 40; 当 y 值到 -2.0 时,表示方框相对于原始位置,向上偏移 80 :

核心代码如下所示,在状态类中维护 Offset 对象,将其传入 AnimatedSlide 的构造函数中。拖拽进度条变化时,更新 offset 对象,重新构建 AnimatedSlide 组件。新旧值直接就可以动画过渡:

---->[状态类]----
Offset offset = Offset.zero;

AnimatedSlide(
  offset: offset,
  duration: const Duration(milliseconds: 500),
  curve: Curves.easeInOut,
  child: Container(color: Colors.red,height: 40,width: 40,),
),

durationcurveonEndImplicitlyAnimated 系列组件的共有属性,分别用于设置动画时长、动画曲线、动画结束回调。后面就不赘述了。


2. AnimatedRotation 旋转动画和 AnimatedScale 缩放动画

AnimatedRotation 组件在构造时需要传入 turns 用于控制旋转角度,旋转的角度值是 turns*2*pi;另外 alignment 参数控制旋转变换中心,变化中心是以组件自身内部坐标为参考系的:

核心代码如下所示,在状态类中维护 _turns 值,在拖拽的范围 0~1 之间。将值传入 AnimatedRotation 的构造函数中。拖拽进度条变化时,更新 _turns 对象,重新构建 AnimatedRotation 组件。新旧值直接就可以动画过渡:

---->[状态类]----
double _turns = 0;

AnimatedRotation(
  turns: _turns,
  duration: const Duration(milliseconds: 500),
  curve: Curves.easeInOut,
  child: Container(
    color: Colors.red,
    height: 40,
    width: 40,
  ),
),

缩放和旋转动画都属于简单的变换动画,AnimatedScale 区别仅在于传入的是缩放参数。这里就不赘述了:


3. AnimatedFractionallySizedBox

AnimatedFractionallySizedBox 在构造中传入宽高的分率,和对齐方式。当三者任意一个属性变化时,都会进行动画过渡。比如这里案例有三个属性动画:

  • 对齐方式从左上到右下
  • 宽度从父区域的 25% 变化到 75%
  • 高度从父区域的 75% 变化到 25%

另外仔细观察可以看出,ImplicitlyAnimated 系列的动画组件有一个特性:

当在动画时长内,值又发生了变化。会自动从当前值过渡到新值。保持动画的连续性。

案例中的代码,通过 selected 状态切换 AnimatedFractionallySizedBox 组件的属性参数,重新构建后就会驱动动画执行:

---->[状态类]----
bool selected = false;

AnimatedFractionallySizedBox(
  widthFactor: selected ? 0.25 : 0.75,
  heightFactor: selected ? 0.75 : 0.25,
  alignment: selected ? Alignment.topLeft : Alignment.bottomRight,
  duration: const Duration(seconds: 1),
  curve: Curves.fastOutSlowIn,
  child: const ColoredBox(
    color: Colors.blue,
    child: FlutterLogo(size: 75),
  ),
),

4. 源码简看

ImplicitlyAnimated 系列的组件可以直接通过修改属性达到动画效果,是非常简单和实用的。对于动画没有特别复杂的操作,可以使用它们。 FlutterUnit 中也收录了其他的 ImplicitlyAnimated 系列组件,大家可以自行查看。

ImplicitlyAnimated 本质上是内部封装了动画控制器,将动画值暴露给子类。拿 AnimatedRotation 组件来说,在构建方面依赖 RotationTransition 组件:

其中动画器 animation 是父类 ImplicitlyAnimatedWidgetState 暴露出来的,动画属性变化时会触发 didUpdateTweens 回调,更新过渡值。这就是 AnimatedRotation 的所有代码,是不是非常简单:


同理 AnimatedSlide 组件,依赖 SlideTransition 滑动变换,其他两个也是类似,就不赘述了。


尾声

《Flutter 动画探索 - 流光幻影》 中,详细介绍过 ImplicitlyAnimated 组件的源码实现,感兴趣的可以去看看。总得来说 ImplicitlyAnimated 系列组件可以屏蔽用户对动画控制器的感知,仅通过属性变化就可以完成动画效果。

但反过来说,由于 ImplicitlyAnimated 组件封装了动画控制器,使用者便无法灵活地操作动画控制器。这就是封装带来便利性的代价。大家可以根据使用的场景,来斟酌使用哪类动画比较合适。 那本文就到这里,谢谢观看。FlutterUnit 在持续收录中,欢迎多多关注。

更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。

注册登录 后评论
    // 作者
    张风捷特烈 发布于 掘金
    • 0
    // 本帖子
    分类
    // 相关帖子
    Coming soon...
    • 0
    Flutter 组件集录 | 隐式动画组件 * 4张风捷特烈 发布于 掘金