Flutter 学习笔记 17 - 交错动画
时间:2022-06-21
本文章向大家介绍Flutter 学习笔记 17 - 交错动画,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
多个动画组合在一起,可能有重叠。每个动画对应一个 Tween 对象,一个 AnimationController 控制所有动画。AnimationController 的值必须在 0.0 到 1.0 之间。
先看一个简单的例子:
class AnimatedLogo extends AnimatedWidget {
// 两个 Animation
static final _opacityTween = new Tween<double>(begin: 0.1, end: 1.0);
static final _sizeTween = new Tween<double>(begin: 0.0, end: 300.0);
AnimatedLogo({Key key, Animation<double> animation})
: super(key: key, listenable: animation);
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
return Center(
child: new Opacity(
// 透明度动画
opacity: _opacityTween.evaluate(animation),
child: new Container(
margin: new EdgeInsets.symmetric(vertical: 10.0),
// 尺寸动画
height: _sizeTween.evaluate(animation),
width: _sizeTween.evaluate(animation),
child: new FlutterLogo(),
),
),
);
}
}
//...
class AnimState extends State<AnimScreen> with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController controller;
@override
initState() {
super.initState();
controller = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = new CurvedAnimation(parent: controller, curve: Curves.easeIn);
controller.forward();
}
Widget build(BuildContext context) {
return AnimatedLogo(animation: animation);
}
// ...
}
对于原来 Animation
animation = Tween(begin: 0.0, end: 300.0).animate(controller)
看 animate 方法的定义
Animation<T> animate(Animation<double> parent) {
return _AnimatedEvaluation<T>(parent, this);
}
而以后调用 .value
时,看源码
@override
T get value => _evaluatable.evaluate(parent);
所以 _sizeTween.evaluate(animation)
这种用法和原来是等价的,只是原来先通过 animation()
方法返回了 Animation,然后直接调用这个 Animation 的 value。现在是直接在 Tween 上通过 evaluate 方法把外界的 Animation 传进去。
下面是个更复杂的例子,在 0.0 到 1.0 间连续做六个动画
15481272243303.png
六个动画创建六个 Tween,创建一个类管理这六个动画,在构造时创建对象
class StaggerAnimation extends StatelessWidget {
final Animation<double> controller;
final Animation<double> opacity;
final Animation<double> width;
final Animation<double> height;
final Animation<EdgeInsets> padding;
final Animation<BorderRadius> borderRadius;
final Animation<Color> color;
StaggerAnimation({ Key key, this.controller }) :
opacity = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.0, 0.100,
curve: Curves.ease,
),
),
),
width = Tween<double>(
begin: 50.0,
end: 150.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.125, 0.250,
curve: Curves.ease,
),
),
),
height = Tween<double>(
begin: 50.0,
end: 150.0
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.250, 0.375,
curve: Curves.ease,
),
),
),
padding = EdgeInsetsTween(
begin: const EdgeInsets.only(bottom: 16.0),
end: const EdgeInsets.only(bottom: 75.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.250, 0.375,
curve: Curves.ease,
),
),
),
borderRadius = BorderRadiusTween(
begin: BorderRadius.circular(4.0),
end: BorderRadius.circular(75.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.375, 0.500,
curve: Curves.ease,
),
),
),
color = ColorTween(
begin: Colors.indigo[100],
end: Colors.orange[400],
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.500, 0.750,
curve: Curves.ease,
),
),
),
super(key: key);
}
然后重写 build 方法
final Animation<double> controller;
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
padding: padding.value, // 内边距动画
alignment: Alignment.bottomCenter,
child: Opacity(
opacity: opacity.value, // 透明度动画
child: Container(
width: width.value, // 宽度动画
height: height.value, // 高度动画
decoration: BoxDecoration(
color: color.value, // 颜色动画
border: Border.all(
color: Colors.indigo[300],
width: 3.0,
),
borderRadius: borderRadius.value, // 圆角动画
),
),
),
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
builder: _buildAnimation, // 动画变化时调用这个函数
animation: controller, // 要执行的动画
);
}
然后构建要做动画的 Widget
class StaggerDemo extends StatefulWidget {
@override
_StaggerDemoState createState() => _StaggerDemoState();
}
class _StaggerDemoState extends State<StaggerDemo> with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
// 构建一个 Controller
_controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future<void> _playAnimation() async {
try {
// 执行一遍再逆向执行一遍
await _controller.forward().orCancel;
await _controller.reverse().orCancel;
} on TickerCanceled {
}
}
@override
Widget build(BuildContext context) {
timeDilation = 10.0;
return Scaffold(
appBar: AppBar(
title: const Text('Staggered Animation'),
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
_playAnimation();
},
child: Center(
child: Container(
width: 300.0,
height: 300.0,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.1),
border: Border.all(
color: Colors.black.withOpacity(0.5),
),
),
child: StaggerAnimation(
controller: _controller.view
),
),
),
),
);
}
}
AnimationController 是 2000ms,而最后的 0.25 没有执行某个动画,逆序最开始也有 0.25,所以中间会有 2000*0.5=1000ms 的时间没有动画效果(Gif 图有点太快了)。
2019-01-22 15_48_53.gif
- POJ--Strange Way to Express Integers
- HDUOJ----More is better(并查集)
- HDUOJ 1099——Lottery
- HDUOJ-----取(m堆)石子游戏
- HDUOJ-----Be the Winner
- HDUOJ-------- Fibonacci again and again
- HDUOJ----Good Luck in CET-4 Everybody!
- 进制转换
- HDUOJ--畅通工程
- poj----Ubiquitous Religions
- POJ----The Suspects
- HDUOJ----剪花布条
- HDUOJ-----F(x)
- HDUOJ---(2203)亲和串
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- [Data Guard全解析]5.Data Guard及ADG日常运维操作
- [Oracle 数据库日常操作] 表空间的日常运维命令
- Java 反射 -超详细讲解(附源码)
- [Data Guard全解析]6.物理备库的Switchover
- com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException异常解决方法
- [Oracle数据库日常操作] Redo Log的相关操作
- [周末往期回顾] 使用requests和fiddler模拟登陆51cto并获取下载币
- [周末往期回顾] 自动备份思科交换机配置
- [打造自己的监控系统]让Django运行自定义命令
- 没想到 Shell 命令竟然还能这么玩?| Shell 玩转大数据分析
- 瞄准器!3D入门实战!拇指射箭!Cocos Creator 3D !
- [周末往期回顾] 使用Django创建网站
- 用 NetworkX + Gephi + Nebula Graph 分析<权力的游戏>人物关系(上篇)
- [Oracle数据库迁移]使用expdp/impdp进行迁移
- [周末往期回顾]使用Django获取Linux性能数据并存放在redis中