文章目录
- ◯、AnimatedBuilder 引入
- 一、创建动画控制器
- 二、创建动画
- 三、创建动画作用的组件
- 四、创建 AnimatedBuilder 关联动画与组件
- 五、动画运行
- 六、完整代码示例
- 七、相关资源
AnimatedBuilder 动画使用流程 :
① 创建动画控制器
② 创建动画
③ 创建动画作用的组件
④ 创建 AnimatedBuilder 关联动画与组件
⑤ 执行动画
◯、AnimatedBuilder 引入
在上一篇博客 【Flutter】Animation 动画 ( AnimatedWidget 动画使用流程 | 创建动画控制器 | 创建动画 | 创建 AnimatedWidget 动画组件 | 动画运行 ) 中 , 使用了 AnimatedWidget 组件实现动画 , 省略了手动添加监听器 , 并在监听器中手动调用 setState 更新动画的操作 ;
使用 AnimatedWidget 方法实现的动画 , 与 Widget 组件的耦合性还是很高 , 这里引入 AnimatedBuilder , 可以将 Animation 动画 和 Widget 组件分离 ;
AnimatedBuilder 可以构建通用 Widget , AnimatedBuilder 可以用于拆分动画 与 组件 ;
动画开发中需要分离的功能 :
- 显示动画作用的组件
- 定义 Animation 动画对象
- 将 Animation 渲染到组件上
AnimatedBuilder 在监听机制上与 AnimatedWidget 类似 , 也是自动添加监听器 , 监听动画的执行过程 , 自动调用 setState 方法更新界面 ;
一、创建动画控制器
AnimationController 构造函数参数说明 :
AnimationController(
{double? value, /// 动画的初始值
Duration? duration, /// 动画正向播放持续时间
Duration? reverseDuration, /// 动画逆序播放持续时间
String? debugLabel, /// 调试期间标识动画的标志
double lowerBound: 0.0, /// 动画最小值
double upperBound: 1.0, /// 动画最大值
AnimationBehavior animationBehavior: AnimationBehavior.normal,
/// 上下文的 TickerProvider , 用于防止屏幕外的动画消耗不必要的资源 ,
/// 一般将 StatefulWidget 作为 vsync 值
required TickerProvider vsync}
)
上述参数中 , 只需要设置 required TickerProvider vsync
参数 与 Duration? duration
参数即可 ;
创建动画控制器代码示例 :
/// 1. 初始化动画控制器
animationController = AnimationController(
// 动画绘制到屏幕外部时, 减少消耗
vsync: this,
// 动画持续时间 2 秒
duration: Duration(seconds: 3),
);
二、创建动画
这里创建 Tween 补间动画 , 设置动画的初始值
0
0
0 , 结束值
300
300
300 , 动画在执行的
3
3
3 秒时间内 ( 动画控制器中指定的动画持续时间 ) , 自动计算出每个时间点的
0
0
0 ~
300
300
300 之间的动画值 ;
创建动画代码示例 :
/// 2 . 构造 Tween 补间动画 ,
/// 设置动画控制器 AnimationController 给该补间动画
/// 动画的值是正方形组件的宽高
animation = Tween<double>(
begin: 0,
end: 300
).animate(animationController)
三、创建动画作用的组件
创建一个纯无状态组件 StatelessWidget , 该组件与 Animation 动画对象各自都是独立的 , 使用 AnimatedBuilder 耦合 动画 与 组件 ;
代码示例 :
/// 3 . 定义纯组件, 动画应用与该组件上
class AnimationWidget extends StatelessWidget{
@override
Widget build(BuildContext context) {
return // 动画的主体组件
// 布局组件中使用动画的值 , 以达到动画效果
Container(
decoration: BoxDecoration(color: Colors.red),
);
}
}
四、创建 AnimatedBuilder 关联动画与组件
创建 AnimatedBuilder , 关联动画与组件 ;
首先要把 AnimatedBuilder , Animation 动画 , Widget 组件 , 都封装在一个 StatelessWidget 组件中 , Flutter 中一切皆组件 ;
然后在这个组件中返回一个包含 AnimatedBuilder 组件的组件 , 其中将 Animation 动画 和 Widget 组件都设置在该 AnimatedBuilder 中 , Animation 动画设置在 animation 字段中 , child 字段需要设置到 build 字段中 , 设置的方法如下 :
AnimatedBuilder(
animation: animation,
builder: (context, child) => Container(
height: animation.value,
width: animation.value,
child: child,
),
child: child,
)
代码示例 :
/// 4 . 将组件与动画结合起来
class AnimationTransition extends StatelessWidget{
/// 构造方法
AnimationTransition({this.child, this.animation});
/// 动画作用的组件
final Widget child;
/// 动画
final Animation<double> animation;
@override
Widget build(BuildContext context) {
/// AnimatedBuilder 会自动监听 animation 的变化
/// 然后渲染 child 组件上的动画
return Column(
children: [
Text("动画状态 : ${animation.status}", textDirection: TextDirection.ltr,),
Text("动画值 : ${animation.value?.round()}", textDirection: TextDirection.ltr,),
Container(height: 50,),
AnimatedBuilder(
animation: animation,
builder: (context, child) => Container(
height: animation.value,
width: animation.value,
child: child,
),
child: child,
)
],
);
}
}
五、动画运行
监听 GestureDetector 的 onTap 点击事件 , 点击该组件后 , 调用 animationController.forward()
方法 , 运行动画 ;
代码示例 :
GestureDetector(
// 5 . 点击按钮开启动画
onTap: (){
/// 按钮点击事件
/// 首先将动画初始化
animationController.reset();
/// 正向执行动画, 即从初始值执行到结束值
animationController.forward();
},
child: Container(
alignment: Alignment.center,
color: Colors.green,
height: 50,
child: Text(
// 显示文本
"动画开始",
/// 文字方向 : 从左到右
textDirection: TextDirection.ltr,
),
),
),
六、完整代码示例
完整代码示例 :
import 'package:flutter/material.dart';
void main() {
runApp(AnimationApp());
}
/// 3 . 定义纯组件, 动画应用与该组件上
class AnimationWidget extends StatelessWidget{
@override
Widget build(BuildContext context) {
return // 动画的主体组件
// 布局组件中使用动画的值 , 以达到动画效果
Container(
decoration: BoxDecoration(color: Colors.red),
);
}
}
/// 4 . 将组件与动画结合起来
class AnimationTransition extends StatelessWidget{
/// 构造方法
AnimationTransition({this.child, this.animation});
/// 动画作用的组件
final Widget child;
/// 动画
final Animation<double> animation;
@override
Widget build(BuildContext context) {
/// AnimatedBuilder 会自动监听 animation 的变化
/// 然后渲染 child 组件上的动画
return Column(
children: [
Text("动画状态 : ${animation.status}", textDirection: TextDirection.ltr,),
Text("动画值 : ${animation.value?.round()}", textDirection: TextDirection.ltr,),
Container(height: 50,),
AnimatedBuilder(
animation: animation,
builder: (context, child) => Container(
height: animation.value,
width: animation.value,
child: child,
),
child: child,
)
],
);
}
}
/// 动画示例主界面组件
/// 该组件是有状态的, 因此需要定义 StatefulWidget 组件
class AnimationApp extends StatefulWidget{
@override
_AnimationAppState createState() => _AnimationAppState();
}
/// 为 StatefulWidget 组件创建 State 类
/// 每个 StatefulWidget 都需要一个配套的 State 类
class _AnimationAppState extends State<AnimationApp>
with SingleTickerProviderStateMixin{
/// 动画类
Animation<double> animation;
/// 动画控制器
AnimationController animationController;
@override
void initState() {
super.initState();
/// 1. 初始化动画控制器
animationController = AnimationController(
// 动画绘制到屏幕外部时, 减少消耗
vsync: this,
// 动画持续时间 2 秒
duration: Duration(seconds: 3),
);
/// 2 . 构造 Tween 补间动画 ,
/// 设置动画控制器 AnimationController 给该补间动画
/// 动画的值是正方形组件的宽高
animation = Tween<double>(
begin: 0,
end: 300
).animate(animationController);
}
/// 该方法与 initState 对应
@override
void dispose() {
/// 释放动画控制器
animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return
Column(
children: [
Container(height: 50,),
GestureDetector(
// 5 . 点击按钮开启动画
onTap: (){
/// 按钮点击事件
/// 首先将动画初始化
animationController.reset();
/// 正向执行动画, 即从初始值执行到结束值
animationController.forward();
},
child: Container(
alignment: Alignment.center,
color: Colors.green,
height: 50,
child: Text(
// 显示文本
"动画开始",
/// 文字方向 : 从左到右
textDirection: TextDirection.ltr,
),
),
),
Container(height: 50,),
AnimationTransition(animation: animation, child: AnimationWidget())
],
);
}
}
运行效果 : 动画值不能更新 ;
七、相关资源
参考资料 :
- Flutter 官网 : https://flutter.dev/
- Flutter 插件下载地址 : https://pub.dev/packages
- Flutter 开发文档 : https://flutter.cn/docs ( 强烈推荐 )
- 官方 GitHub 地址 : https://github.com/flutter
- Flutter 中文社区 : https://flutter.cn/
- Flutter 实用教程 : https://flutter.cn/docs/cookbook
- Flutter CodeLab : https://codelabs.flutter-io.cn/
- Dart 中文文档 : https://dart.cn/
- Dart 开发者官网 : https://api.dart.dev/
- Flutter 中文网 : https://flutterchina.club/ , http://flutter.axuer.com/docs/
- Flutter 相关问题 : https://flutterchina.club/faq/ ( 入门阶段推荐看一遍 )
- GitHub 上的 Flutter 开源示例 : https://download.csdn.net/download/han1202012/15989510
- Flutter 实战电子书 : https://book.flutterchina.club/chapter1/
重要的专题 :
- Flutter 动画参考文档 : https://flutterchina.club/animations/
博客源码下载 :
-
GitHub 地址 : https://github.com/han1202012/flutter_animation ( 随博客进度一直更新 , 有可能没有本博客的源码 )
-
博客源码快照 : https://download.csdn.net/download/han1202012/16188742 ( 本篇博客的源码快照 , 可以找到本博客的源码 )