这是我参与更文挑战的第6天,活动详情查看: 更文挑战
本文已参与 周末学习计划,点击查看详情
前言
前一篇我们聊了几个纯粹的 Flutter 单属性动画组件,这篇我们看一下稍微复杂点的动画组件「AnimatedCrossFade、AnimatedSwitcher、AnimatedSize」,这里的复杂
是指使用上有更多注意的点和配置上的灵活性。
AnimatedCrossFade(动画淡入淡出)
有时我们需要两个 Widget 之间切换,直接切换非常的突兀,我们可以加一个淡入淡出的效果, Flutter 为我们准备好了,来看看效果
下面代码就很简单,分别设置两个 child Widget 即可
GestureDetector(
onTap: () {
// 点击切换
this.crossFirst = !crossFirst;
setState(() {});
},
child: AnimatedCrossFade(
// 第一个 child
firstChild: DescContainer(
height: 60,
width: width,
color: Colors.black,
text: 'AnimatedCrossFade firstChild',
),
// 第二个 child
secondChild: DescContainer(
height: 40,
width: 300,
color: Colors.pink,
text: 'AnimatedCrossFade secondChild',
),
// 切换显示 child
crossFadeState: crossFirst
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
duration: duration,
),
),
优化突兀感
虽然实现切换了,但是在 firstChild => secondChild
的时候还是非常的突兀,我们需要通过自定义设置 layoutBuilder
属性来优化。
看源码
这里默认的 layoutBuilder
使用的是 defaultLayoutBuilder
我们改动两个地方即可。
AnimatedCrossFade(
...
layoutBuilder:(topChild, topChildKey, bottomChild, bottomChildKey) {
return Stack(
clipBehavior: Clip.none,
// 这里设置居中对齐
alignment: Alignment.center,
children: <Widget>[
Positioned(
key: topChildKey,
child: topChild,
),
Positioned(
key: bottomChildKey,
// 去掉左边和右边定位
// left: 0.0,
top: 0.0,
// right: 0.0,
child: bottomChild,
),
],
);
},
),
其他属性
firstChild
第一个 child widgetsecondChild
第二个 child widgetfirstCurve
第一个曲线动画secondCurve
第二个曲线动画sizeCurve
大小的曲线动画,为什么会有这个属性,我们下面会讲到
alignment
对齐方式crossFadeState
淡入状态duration
动画时间reverseDuration
返回动画时间layoutBuilder
布局构建起,就是我们上面说的
AnimatedSize(动画大小)
现在继续回去翻看一下 AnimatedCrossFade
源码你会发现就是用过 ClipRect
剪裁(可以看我专栏中的《Flutter 中各种剪裁 Widget 的使用》)+ AnimatedSize
实现的。
我们先看看实现的效果
GestureDetector(
onTap: () {
this.size = size == 200 ? 100 : 200;
setState(() {});
},
child: AnimatedSize(
duration: duration,
// 这里要混入 TickerProviderStateMixin 才可以
vsync: this,
clipBehavior: Clip.antiAlias,
alignment: Alignment.center,
child: FlutterLogo(
size: size,
),
),
),
这里你看到的其实是假象,我们改变一下它的 child 看看。
AnimatedSize(
child: DescContainer(
// 这里的 ! 标识我们确定它不为空,是空安全的知识点
color: Colors.pink[300]!,
height: size,
width: size,
text: 'AnimatedSize',
),
)
其实看到效果和我们上面 AnimatedCrossFade
是一样的,在第二次转换的时候是非常突兀的,然后在返回看看 FlutterLogo
的实现
哈哈哈哈哈,看到这里你就明白了吧,和我专栏中聊的 《Flutter 中使用 AnimatedContainer 让你的 Widget 动起来》实现是一致的,要怎么处理呢?
- 可以参照
AnimatedCrossFade
来使用 LayoutBuilder - 可以阅读
AnimatedContainer
源码来优化,暂时不展开聊了
AnimatedSwitcher(动画切换)
未设置 key | 设置了 key |
GestureDetector(
onTap: () {
this.playing = !playing;
setState(() {});
},
child: AnimatedSwitcher(
duration: duration,
child: Icon(
playing ? Icons.pause_circle : Icons.play_circle,
// 这里的 key 非常重要
key: ValueKey(playing),
size: 80,
color: Colors.blue,
),
),
),
扩展一下
我们这里切换的时候目前只是渐变的效果,我们还可以加上缩放等效果,这时就要用到 transitionBuilder
了
ScaleTransition | FadeTransition | ScaleTransition + FadeTransition |
AnimatedSwitcher(
duration: duration,
transitionBuilder: (child, animation) {
// 缩放效果
return ScaleTransition(
scale: animation,
// 渐变效果
child: FadeTransition(
opacity: animation,
child: child,
),
);
},
child: Icon(
playing ? Icons.pause_circle : Icons.play_circle,
// 这里的 key 非常重要
key: ValueKey(playing),
size: 80,
color: Colors.blue,
),
)
Flutter 内置了还有很多 Transition
,如 SizeTransition、PositionedTransition、AlignTransition、SlideTransition、等
可以去很方便的组合使用,期待你有很多的发现和创意。
源码仓库
基于 Flutter 🔥 最新版本
参考链接
- AnimatedCrossFade (Flutter Widget of the Week)
- Flutter-AnimatedCrossFade
- Flutter-AnimatedSize
- AnimatedSwitcher (Flutter Widget of the Week)
- Flutter-AnimatedSwitcher
- Flutter-ScaleTransition
- FadeTransition (Flutter Widget of the Week)
- Flutter-FadeTransition
关注专栏
- 此文章已收录到下面👇 的专栏,可以直接关注
- 更多文章继续阅读|系列文章持续更新
👏 欢迎点赞➕收藏➕关注,有任何问题随时在下面👇评论,我会第一时间回复哦