写在前面
简单动画开发,这部分内容是我对Flutter动画相关API的分析和思考,以及为什么会有flutter_steps_animation
只想学习flutter_steps_animation的读者可以直接翻到 复杂动画开发 开始阅读
简单动画开发
官方示例
class Spinner extends StatefulWidget {
@override
_SpinnerState createState() => _SpinnerState();
}
class _SpinnerState extends State<Spinner> with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 10),
vsync: this,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
child: Container(
width: 200.0,
height: 200.0,
color: Colors.green,
child: const Center(
child: Text('Wee'),
),
),
builder: (BuildContext context, Widget child) {
return Transform.rotate(
angle: _controller.value * 2.0 * math.pi,
child: child,
);
},
);
}
}
效果如图
除了AnimatedBuilder之外,还有
等等,被进一步封装的Widget
看上去还挺强大,甚至还想扣一波666?但是现实世界真的这么简单吗?
Widget功能单一
有没有注意到,以上所有这些Widget都只能完成一个单独的动画?
从上面的例子扩展,如果我还想要颜色同步(同步的意思是指多个动画使用相同的曲线,相同的周期)变化,还想要周期性的缩放,甚至还想改下文字的透明度?就像这样:
读者可以自行尝试实现这样的动画,我的结论是:如果写法不做大的调整,可读性/可维护性会非常差
问题在哪
一个Widget只做一件事,这是Flutter framework 设计的基本理念之一,这当然很好,它带来了非常棒的分层设计,以及小白用户的较好体验,但是矛盾也发生在这里:
框架设计者与我们这些App开发者所理解的“一件事”是不一样的
对App开发者而言,在业务逻辑上做一件事,实现多个完全不同步的动画,也只是一件事,但官方现阶段显然没有想好如何提供这样的Widget,这也是我开发flutter_steps_animation的原因。
所以到正题了,我来介绍我做了哪些工作😁
复杂动画开发
实际的例子
这是我所开发的一个弹窗动画
整个动画只使用了一个AnimationBuilder
当然工程代码就不能给你们看了233
回来看看刚才的demo
来看看使用flutter_steps_animation框架后的代码实现:
class Spinner extends StatefulWidget {
@override
_SpinnerState createState() => _SpinnerState();
}
class _SpinnerState extends State<Spinner> with SingleTickerProviderStateMixin {
StepsAnimation stepsAnimation;
@override
void initState() {
super.initState();
final builder = StepsAnimationBuilder();
//可以添加多个OneStepAnimationBuilder,总持续时间为每个步骤相加
builder.addStepBuilder(_multipleAnimationBuilder());
stepsAnimation = builder.animation(this);
}
OneStepAnimationBuilder _multipleAnimationBuilder() {
//每一个step可以添加各种各样,乃至相同key的动画
//但是一个step只有一个创建Widget的方法
//如果动画有widget层面的较大变化,应分为多个step
final builder = MultipleAnimationBuilder(
//该step持续时间10s
duration: Duration(seconds: 10),
buildAnimation: (context, map) {
return Transform.scale(
scale: map['scale'].value,
child: Transform.rotate(
angle: map['angle'].value,
child: Container(
width: 200.0,
height: 200.0,
color: map['color'].value,
child: Center(
child: Opacity(
opacity: map['opacity'].value,
child: Text('Wee'),
),
),
),
),
);
});
builder
//旋转角度动画,10s旋转一周
.addAnimatable(
animatable: Tween<double>(begin: 0, end: 2 * math.pi),
from: Duration.zero,
duration: Duration(seconds: 10),
key: 'angle')
//缩放动画,从1s开始,持续2s
.addAnimatable(
animatable: Tween<double>(begin: 0.8, end: 1.3),
from: Duration(seconds: 1),
duration: Duration(seconds: 2),
key: 'scale')
//第二个缩放动画,从7s开始,持续2s
.addAnimatable(
animatable: Tween<double>(begin: 1.3, end: 0.8),
from: Duration(seconds: 7),
duration: Duration(seconds: 2),
key: 'scale')
//颜色变化动画,10s从绿色变化到蓝灰色
.addAnimatable(
animatable: ColorTween(begin: Colors.green, end: Colors.blueGrey),
from: Duration.zero,
duration: Duration(seconds: 10),
key: 'color')
//文字透明度动画,从0s开始,持续5s,从不透明到透明
.addAnimatable(
animatable: Tween<double>(begin: 1, end: 0),
from: Duration(seconds: 0),
duration: Duration(seconds: 5),
key: 'opacity')
//第二个文字透明度动画,从5s开始,持续5s,从透明到不透明
.addAnimatable(
animatable: Tween<double>(begin: 0, end: 1),
from: Duration(seconds: 5),
duration: Duration(seconds: 5),
key: 'opacity');
return builder;
}
@override
void dispose() {
stepsAnimation.controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
stepsAnimation.controller.forward();
},
child: AnimatedBuilder(
animation: stepsAnimation.controller,
builder: stepsAnimation.builder,
),
);
}
}
对开发过动画的同学来说都很简单吧?
flutter_steps_animation
解决什么问题
解决复杂的、多步骤的动画,实现困难,以及可读性、可维护性差的问题
特性
本框架为你提供这些特性:
- 分步骤(step)构建动画
- 单步骤中添加多个完全独立的动画
- 重复key值的动画(持续时间上不能相互覆盖)
- 整合多个步骤在同一个Controller
不同的Builder
基于代码可读性的考虑,目前添加有这些Builder:
-
StepsAnimationBuilder
这就是最核心的Builder了,使用方法见上面的demo代码
-
NoneAnimationBuilder
事实上没有动画,只是想在多个步骤的动画间,拖拖时间
事实上也可以通过延长上一个步骤的持续时间做到,主要目的是代码可读性更高
-
SingleAnimationBuilder
只有单个动画的Step,在动画的某些简单步骤中,使用MultipleAnimation是杀鸡用牛刀,同样是为了代码可读性更高
-
MultipleAnimationBuilder
核心的动画构造Builder,使用方法同样见上面的demo代码
用起来把少年
目前的版本是1.1.0,最新版本在pub查看
dependencies:
flutter_steps_animation: ^1.1.0
最后
欢迎Star, 欢迎PR,有Issue也请务必提出