1、Animation动画的抽象类,能够实现对动画状态的监听和动画的监听(addStatusListener和addListener)。
2、AnimationController动画的管理类
3、CurvedAnimation管理动画的运动曲线
4、Tween自定义AnimationController中lowerBound和lowerBound值
实现一个基本的动画(从小变大,再从大变小),并实现对动画状态的监听。
class _DemoWidgetState extends State with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
super.initState();
// 创建动画
_controller = AnimationController(
duration: Duration(seconds: 1), vsync: this
);
// 设置动画的执行曲线为线性
_animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
// 修改lowerBound和upperBound默认值
_animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
// 监听状态
_animation.addListener(() {
setState(() {
});
});
// 监听动画执行的状态
_animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
} else if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
// 执行动画
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
// 将动画的值赋值给对应的widget
height: _animation.value,
width: _animation.value,
child: FlutterLogo(),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
1、上面的动画要执行必须要在addListener中改变state的值
2、并且在state改变的时候,build中的widget又会重新构建
AnimatedWidget的使用需要创建一个重用动画的widget。
// 动画widget
class AnimatedLogo extends AnimatedWidget {
AnimatedLogo(Animation animation): super(listenable: animation);
Widget build(BuildContext context) {
final Animation _animation = listenable;
return Center(
child: Container(
height: _animation.value,
width: _animation.value,
child: FlutterLogo(),
),
);
}
}
// AnimatedWidget简化
class _DemoWidgetState extends State with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(seconds: 1), vsync: this
);
_animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
_animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
_animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
} else if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
_controller.forward();
}
@override
Widget build(BuildContext context) {
return AnimatedLogo(_animation);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
AnimatedWidget的缺点:
1、AnimatedWidget创建的动画每次都会创建一个widget集成AnimatedWidget
2、AnimatedWidget子类中的build中每次都会重新构建,child层级深的时候性能不好
class _DemoWidgetState extends State with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(seconds: 1), vsync: this
);
_animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
_animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
// 监听动画执行的状态
_animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
} else if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
animation: _animation,
builder: ((ctx, child) {
return Container(
height: _animation.value,
width: _animation.value,
child: child,
);
}),
// 这里对动画widget引用,减少构建
child: FlutterLogo(),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
并行动画就是在同一时刻有多个状态的值在变化。
在上面动画的基础上增加透明度变化的动画。
class _DemoWidgetState extends State with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
Animation _opacity_animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(seconds: 1), vsync: this
);
_animation = CurvedAnimation(parent: _controller, curve: Curves.linear);
_animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
// 监听动画执行的状态
_animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
} else if (status == AnimationStatus.dismissed) {
_controller.forward();
}
});
// 透明度
_opacity_animation = Tween(begin: 0.1, end: 1.0).animate(_controller);
_controller.forward();
}
@override
Widget build(BuildContext context) {
print("build");
return Center(
child: AnimatedBuilder(
animation: _animation,
builder: ((ctx, child) {
return Container(
height: _animation.value,
width: _animation.value,
child: child,
);
}),
child: Opacity(child: FlutterLogo(), opacity: _opacity_animation.value,),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Hero动画指一个页面转场到下一个页面。
// 第一个页面
class DemoWidget extends StatelessWidget {
static const HeroTag = "TestHeroTag";
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Hero(child: Image.network("https://picsum.photos/250?image=10"), tag: HeroTag,),
onTap: () {
Navigator.push(context, PageRouteBuilder(pageBuilder: (ctx, anim1, anim2) {
return FadeTransition(
opacity: anim1,
child: NextPage(),
);
}));
},
);
}
}
// 第二个页面
class NextPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("NextPage"),),
body: Center(
child: GestureDetector(
child: Hero(
child: Image.network("https://picsum.photos/250?image=10", width: 100, height: 100,),
tag: DemoWidget.HeroTag,),
onTap: () {
Navigator.pop(context);
},
),
),
);
}
}