Flutter中的动画介绍
动画的控制
使用 AnimationController 主要是对动画进行控制,包含的操作有启动forward()、停止stop() 、反向播放 reverse()等。 下面的代码就是创建一个控制器
AnimationController controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 3000));
创建 AnimationController 的时候需要传递一个 vsync 参数,它接收一个 TickerProvider 类型的对象,它主要是创建一个通过 SchedulerBinding 来添加屏幕刷新回调的Ticker,这样每次屏幕刷新都会调用 TickerCallback,这样会防止屏幕外动画消耗不必要的资源,比如锁屏后屏幕会停止刷新。一般是在实现动画的类上进行 with TickerProviderStateMixin 操作。
动画的实现
使用 Animation 来实现动画,Animation 是一个抽象类,Animation 对象是一个在一段时间内依次生成一个区间(Tween)之间值的类。Animation 对象在整个动画执行过程中输出的值可以是线性的、曲线的、一个步进函数或者任何其他曲线函数等等。 我们可以通过 Animation 来监听动画每一帧以及执行状态的变化,由于 AnimationController 是 Animation 的派生类,所以 AnimationController 也可以调用
Animation().addListener()
Animation().addStatusListener()
CurvedAnimation 是 Animation 的子类,实现的是线性变换动画,比如 linear(匀速的)、decelerate(匀减速)、ease(开始加速,后面减速)、easeIn(开始慢,后面快)、easeOut(开始快,后面慢)、easeInOut(开始慢,然后加速,最后再减速)
CurvedAnimation curve = CurvedAnimation(parent: controller, curve: Curves.easeIn);
我们可以使用 Tween 生成不同的值来表示 UI 不同的动画值
Tween tween = Tween<double>(begin: -1.0, end: 1.0);
Tween color = ColorTween(begin: Colors.black12, end: Colors.black);
要使用Tween对象,需要调用其 animate() 方法,然后传入一个控制器对象
Animation moonRotationAnim = Tween<double>(begin: 0.0, end: 1.0,).animate(_moonFadeController);
做一个启动动画
这个启动动画包含一个旋转的月亮,一个移动的蓝色半圆还有一个灯光
class AnimationPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _AnimationState();
}
}
class _AnimationState extends State<AnimationPage> with TickerProviderStateMixin {
///月亮背景
AnimationController _moonController;
AnimationController _moonFadeController;
AnimationController _moonRotationController;
AnimationController _moonSlideController;
Animation _moonRotationAnim;
Animation _moonFadeAnimation;
Animation _moonSlideAnimation;
///蓝色半圆背景
AnimationController _semicircleFadeController;
Animation _semicircleFadeAnimation;
Animation _semicircleSlideAnimation;
///灯光背景
AnimationController _lightController;
Animation _lightFadeAnimation;
Animation _lightSlideAnimation;
@override
void initState() {
// TODO: implement initState
super.initState();
_initAnimation();
_handlerInitAnimation();
}
///记得销毁
@override
dispose() {
_moonController.dispose();
_moonFadeController.dispose();
_moonRotationController.dispose();
_moonSlideController.dispose();
_semicircleFadeController.dispose();
_lightController.dispose();
super.dispose();
}
_handlerInitAnimation() {
_moonController.addStatusListener((status) {
if (status == AnimationStatus.forward) {
print("动画开始");
} else if (status == AnimationStatus.completed) {
print("动画结束");
}
});
}
_initAnimation() {
///月亮背景
_moonController = AnimationController(vsync: this, duration: Duration(milliseconds: 3000))
..addListener(() {
if (_moonFadeController.isDismissed) {
_moonFadeController.forward();
}
if (_moonRotationController.isDismissed) {
_moonRotationController.forward();
}
if (_lightController.isDismissed) {
_lightController.forward();
}
if (_semicircleFadeController.isDismissed && _moonController.value > 0.7) {
_semicircleFadeController.forward();
}
if (_moonSlideController.isDismissed && _moonController.value > 0.8) {
_moonSlideController.forward();
}
});
_moonFadeController = AnimationController(vsync: this, duration: Duration(milliseconds: 500));
_moonRotationController = AnimationController(vsync: this, duration: Duration(milliseconds: 3000));
_moonSlideController = AnimationController(vsync: this, duration: Duration(milliseconds: 700));
_moonFadeAnimation = Tween<double>(begin: 0.0, end: 1.0,).animate(_moonFadeController);
_moonRotationAnim = Tween<double>(begin: 0, end: -0.125,).animate(_moonRotationController);
_moonSlideAnimation = Tween<Offset>(begin: Offset.zero, end: const Offset(0.1, 0)).animate(_moonSlideController);
///蓝色半圆背景
_semicircleFadeController = AnimationController(vsync: this, duration: Duration(milliseconds: 800));
_semicircleSlideAnimation = Tween<Offset>(begin: Offset.zero, end: const Offset(-0.2, 0)).animate(_semicircleFadeController);
_semicircleFadeAnimation = Tween<double>(begin: 0.0, end: 1.0,).animate(_semicircleFadeController);
///灯光背景
_lightController = AnimationController(vsync: this, duration: Duration(milliseconds: 500));
_lightFadeAnimation = Tween<double>(begin: 0.0, end: 1.0,).animate(_lightController);
_lightSlideAnimation = Tween<Offset>(begin: Offset.zero, end: const Offset(0.4, 0)).animate(_lightController);
}
@override
Widget build(BuildContext context) {
///启动动画
_moonController.forward();
double size = MediaQuery.of(context).size.width * 0.54;
double margin = MediaQuery.of(context).size.width * 0.51;
return Scaffold(
backgroundColor: Color(0xff000000),
body: Stack(
children: <Widget>[
///背景半圆(透明度低)
Container(
alignment: Alignment.center,
margin: EdgeInsets.only(bottom: margin),
///动画组件
child: FadeTransition(
///控制 child 透明度的动画
opacity: _semicircleFadeAnimation,
///动画组件
child: SlideTransition(
///实现相对自身的位移
position: _semicircleSlideAnimation,
child: Image.asset(
'assets/images/splash_d_back.png',
width: size,
height: size,
),
),
),
),
///月亮
Container(
alignment: Alignment.center,
margin: EdgeInsets.only(bottom: margin),
///透明度
child: FadeTransition(
///位移
child: SlideTransition(
///旋转
child: RotationTransition(
child: Image.asset(
'assets/images/splash_moon.png',
width: size,
height: size,
),
turns: _moonRotationAnim,
),
position: _moonSlideAnimation,
),
opacity: _moonFadeAnimation,
),
),
///背景半圆(透明度高)
Container(
alignment: Alignment.center,
margin: EdgeInsets.only(bottom: margin),
child: FadeTransition(
child: SlideTransition(
child: Image.asset(
'assets/images/splash_d_front.png',
width: size,
height: size,
),
position: _semicircleSlideAnimation,
),
opacity: _semicircleFadeAnimation,
),
),
///灯光
Container(
alignment: Alignment.topCenter,
child: FadeTransition(
child: SlideTransition(
child: Image.asset(
'assets/images/splash_light.png',
scale: 3.0,
),
position: _lightSlideAnimation,
),
opacity: _lightFadeAnimation,
),
),
],
),
);
}
}
其他
当然 Flutter 中的动画还有其他的应用,比如路由动画、Hero 动画、动画组件等等,总的来说 Flutter 中的动画使用起来简单方便了许多,用到了可以看一下~