Flutter 组件集录 | 隐式动画组件 * 4
最近盘点 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,),
),
duration
、curve
、onEnd
是 ImplicitlyAnimated 系列组件的共有属性,分别用于设置动画时长、动画曲线、动画结束回调。后面就不赘述了。
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 站 。