Flutter(6)-动画(平移/缩放/旋转/Alpha)
2019-09-26 本文已影响0人
BoxJing
本篇简单介绍下在Flutter中动画的实现以及示例平移、缩放、旋转和alpha动画。
1.动画相关知识介绍
在Flutter中Widget动画的组成有下面这些:
-
Animation
:动画库中的一个核心类,它生成指导动画的值; -
CurvedAnimation
:将动画过程抽象为一个非线性曲线; -
AnimationController
:用来管理管理动画,常用的方法有forward()
:启动动画;reverse({double from}
:倒放动画;reset()
:重置动画,将其设置到动画的开始位置;stop({ bool canceled = true })
:停止动画。 -
Tween
:AnimationController对象的范围从0.0到1.0。如果您需要不同的范围或不同的数据类型,则可以使用Tween
来配置动画以生成不同的范围或数据类型的值。
在开发的过程中我们用AnimatedWidget与AnimatedBuilder可以更简练的方便我们对Widget进行动画的操作:
-
AnimatedWidget
:使用它可以简化我们对动画的使用,在不使用AnimatedWidget
的情况下需要手动调用动画的addListener()
,并在回调中添加setState()
才能看到动画效果,而使用AnimatedWidget
我们就可以简化这一操作。 -
AnimatedBuilder
: 用于构建动画的通用Widget,可以理解为是拆分动画的一个工具类,借助它我们可以将动画和widget进行分离,更加的好管理。
2.平移动画
我们直接用SlideTransition
来一个平移动画示例:
import 'package:flutter/material.dart';
class BoxMoveAnimation extends StatefulWidget {
BoxMoveAnimation({Key key, this.title}) : super(key: key);
final String title;
@override
_BoxMoveAnimationState createState() => _BoxMoveAnimationState();
}
class _BoxMoveAnimationState extends State<BoxMoveAnimation> with TickerProviderStateMixin {
AnimationController controller;
Animation<Offset> animation;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Container(
//SlideTransition 用于执行平移动画
child: SlideTransition(
position: animation,
//将要执行动画的子view
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
),
),
);
}
@override
void initState() {
// TODO: implement initState
super.initState();
controller =
AnimationController(duration: Duration(milliseconds: 2000), vsync: this);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
//AnimationStatus.completed 动画在结束时停止的状态
debugPrint('完成');
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
//AnimationStatus.dismissed 表示动画在开始时就停止的状态
debugPrint('消失');
controller.forward();
// controller.dispose();
}
});
animation =
Tween(begin: Offset.zero, end: Offset(1.0, 0.0)).animate(controller);
//开始执行动画
controller.forward();
}
}
看一下运行效果:
可以看到我们利用
SlideTransition
来做平移动画还是非常方便的,直接将animation
设置为position
属性就可以了。
3.缩放动画
直接用ScaleTransition
来一个缩放动画的示例:
class BoxScaleAnimation extends StatefulWidget {
BoxScaleAnimation({Key key, this.title}) : super(key: key);
final String title;
@override
_BoxScaleAnimationState createState() => _BoxScaleAnimationState();
}
class _BoxScaleAnimationState extends State<BoxScaleAnimation> with TickerProviderStateMixin {
AnimationController controller;
@override
void initState() {
// TODO: implement initState
super.initState();
controller =
AnimationController(duration: const Duration(seconds: 2), vsync: this);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
controller.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body:Center(
child: ScaleTransition(
alignment: Alignment.center,
scale: controller,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
),
),
),
);
}
@override
void dispose() {
super.dispose();
controller.dispose();
}
}
看一下运行效果:
4.旋转动画
用RotationTransition
来一个缩放动画的示例:
class BoxRotationAnimation extends StatefulWidget {
BoxRotationAnimation({Key key, this.title}) : super(key: key);
final String title;
@override
_BoxRotationAnimationState createState() => _BoxRotationAnimationState();
}
class _BoxRotationAnimationState extends State<BoxRotationAnimation> with TickerProviderStateMixin {
AnimationController controller;
Animation animation;
@override
void initState() {
// TODO: implement initState
super.initState();
controller =
AnimationController(duration: const Duration(seconds: 3), vsync: this);
animation =
Tween(begin: 0.0, end: 0.25).animate(controller);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
controller.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body:Center(
child: RotationTransition(
alignment: Alignment.center,
turns: animation,
child: Container(
width: 160,
height: 160,
color: Colors.green,
child: Center(
child: Text('Box'),
),
),
),
),
);
}
@override
void dispose() {
super.dispose();
controller.dispose();
}
}
看一下运行效果:
旋转的动画中我们对动画的旋转的值进行了限制,默认的情况下旋转角度是360°,代码限制到了0.25也就是90°。就像前面说的
Animation
用来生成指导动画的值。
5.Opacity动画
用FadeTransition
来一个Opacity动画的示例:
class BoxOpacityAnimation extends StatefulWidget {
BoxOpacityAnimation({Key key, this.title}) : super(key: key);
final String title;
@override
_BoxOpacityAnimationState createState() => _BoxOpacityAnimationState();
}
class _BoxOpacityAnimationState extends State<BoxOpacityAnimation> with TickerProviderStateMixin {
AnimationController controller;
Animation animation;
@override
void initState() {
// TODO: implement initState
super.initState();
controller =
AnimationController(duration: const Duration(seconds: 2), vsync: this);
animation =
Tween(begin: 0.0, end: 1.0).animate(controller);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
print("completed");
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
print("dismissed");
controller.forward();
} else if (status == AnimationStatus.forward) {
print("forward");
} else if (status == AnimationStatus.reverse) {
print("reverse");
}
});
controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body:Center(
child: FadeTransition(
opacity: animation,
child: Container(
width: 160,
height: 160,
color: Colors.green,
child: Center(
child: Text('Box'),
),
),
),
),
);
}
@override
void dispose() {
super.dispose();
controller.dispose();
}
}
看一下运行效果:
通过以上示例,我们会发现官方给我们封装的
AnimatedWidget
的确非常的方便,能够满足我们一般的动画需求,这里必须列一下Flutter中文网的动画介绍,里面的Hero 动画是一个非常好的示例,系统封装的动画Widget非常好用,可以自己去看看,Animatedbuilder的使用可以点击这里直接看到,文中所有的代码都可以在Github:BoxJ/Flutter-daydayup中下载,本篇代码的文件夹是boxdemo_006
,欢迎一起交流!