动画基本原理

我们首先在 State 类里声明 Animation 类型和 AnimationControler 类型,
Animation 是负责产生变化值的控件,而 Controler 是 负责动画的生成的。
注意,如果需要用的动画控件,类声明必须要跟着 with SingleTickerProviderStateMixin如果在不同时刻有着不同的动画效果,就涉及多个 controler 此时就要声明 with TickerProviderStateMixin

1
2
3
Animation<double> animation;
AnimationController controller;
Animation<double> animationAI;

方法重写

如果想要具体定义动画是怎样进行的,一定要重写 initState()dispose()。如下方代码所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@override
void initState() {
super.initState();
//设置 control 的持续时间
controller = new AnimationController(
duration: const Duration(seconds: 2), vsync: this);
//以下是产生动画的核心代码,设置了开始状态和结束状态
//这个值和animation应用的控件属性有关,下面会细说
animation = new Tween(begin: -1.0, end: -0.25).animate(
CurvedAnimation(parent: controller, curve: Curves.fastOutSlowIn))
..addStatusListener((status) {
//..addStateListener 可以监听动画是否完成
if (status == AnimationStatus.completed) {
_pressCard(myCard);
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
animationAI = new Tween(begin: 1.0, end: 0.25).animate(
CurvedAnimation(parent: controller, curve: Curves.fastOutSlowIn));
}

@override
void dispose() {
controller.dispose();
super.dispose();
}

我们在 build 函数外面定义了动画之后,我们就可以在控件中应用他们了

在控件中应用动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
AnimatedBuilder(
animation: controller,
builder: (BuildContext context, Widget child) {
return Transform(
transform: Matrix4.translationValues(
animationAI.value * width, 0.0, 0.0),
child: new Center(
child: Container(
padding: const EdgeInsets.only(top: 16.0),
width: 100.0,
height: 100.0,
child: Image(
image: ExactAssetImage("$aiPicPath"),
width: 40,
height: 40,
),
),
),
);
}
),

在要使用动画的控件位置,首先要声明一个 AnimationBuilder ,并且首先定义它的 animation属性,将这个控件的动画发生与 control 绑定在一起,最后再builder 返回一个动画类型,我的 App 里返回的是一个 Transform 类似于平移的一个动画,核心代码是 transform: Matrix4.translationValues(animationAI.value * width, 0.0, 0.0), 此段代码效果则是产生平移效果。效果如下

平移动画效果
平移动画效果

重置、开启动画

1
2
controller.reset();
controller.forward();

我们将以上两行代码添加到 onPressed 属性中,这样每次点击按钮的时候都会重置并且播放动画。

setState 和 addStatusListener

在 Flutter 中,带有 State 字样的基本都会更新UI,onPressed 中的 setState 函数可以让其中改变的参数马上更新到 UI ,其中的函数一经修改,setState 会立即寻找页面中会调用到该参数的位置,迅速刷新。

addStateListener 同样也是这个含义,他监听动画的状态,以便在动画停止时(或其他状态)用户可以定义参数变化,来改变UI,在这里的应用就是,当动画播放完之后,再调用结果通知 dialog,如果不这样做的话,动画和 dialog 同时触发,没有效果。