AnimatedWidget
之前我们写的例子通过addListener()
和setState()
来更新UI。AnimatedWidget
类封装了调用setState()
的细节,并允许我们将widget
分离出来。我们就可以省略掉addListener()
和setState()
。
AnimatedWidget
是一个有状态的 StatefulWidget
小部件,通过指定 Listenable
更改值时重建小部件。
AnimatedWidget
对于无状态的窗口小部件比较实用;含有众多子类动画。比如:一下都是显性动画
- AlignTransition
- AnimatedBuilder
- AnimatedModalBarrier
- DecoratedBoxTransition
- DefaultTextStyleTransition
- PositionedTransition
- RelativePositionedTransition
- RotationTransition
- ScaleTransition
- SizeTransition
- SlideTransition
构造函数
const AnimatedWidget({
super.key,
required this.listenable,
}) : assert(listenable != null);
这意味着它需要传递一个listenable
类型为Listenable
。
AnimatedWidget
创建动画
拿我们上一个图片逐渐放大的案例来改写。
- 创建 AnimatedWidget 动画组件
class ScaleImage extends AnimatedWidget{
//构造函数
const ScaleImage({
Key? key,
required Animation<double> animation
}):super(key: key,listenable: animation);
@override
Widget build(BuildContext context){
// 获取动画
final _animation = listenable as Animation<double>;
return Center(
// 布局组件中使用动画的值 , 以达到动画效果
child: Image.asset('images/avatar.jpg',width: _animation.value,height: _animation.value,),
);
}
}
- 引入创建好的组件
ScaleImage
,完整代码
import 'package:flutter/material.dart';
class ScaleImage extends AnimatedWidget{
//构造函数
const ScaleImage({
Key? key,
required Animation<double> animation
}):super(key: key,listenable: animation);
@override
Widget build(BuildContext context){
// 获取动画
final _animation = listenable as Animation<double>;
return Center(
// 布局组件中使用动画的值 , 以达到动画效果
child: Image.asset('images/avatar.jpg',width: _animation.value,height: _animation.value,),
);
}
}
class AnimatedWidgetPage extends StatefulWidget {
const AnimatedWidgetPage({Key? key}) : super(key: key);
@override
State<AnimatedWidgetPage> createState() => _AnimatedWidgetPageState();
}
class _AnimatedWidgetPageState extends State<AnimatedWidgetPage> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
// TODO: implement initState
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this
);
//使用Tween图片宽高从0变到300
_animation = Tween(begin: 0.0,end: 300.0).animate(_controller);
//启动动画正向执行
_controller.forward();
}
@override
void dispose() {
// TODO: implement dispose
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:const Text('AnimatedWidget'),),
body: Center(
child: ScaleImage(
animation: _animation,// 传入动画对象 _animation
),
)
);
}
}