官方文档android
Animation
对象,是 Flutter
动画库中的核心类,插入用于引导动画的值Animation
对象知道当前动画的状态(如:动画是否开始,中止,前进或者后退),但对屏幕上显示的内容一无所知AnimationController
对象管理着 Animation
CurvedAnimation
将动画定义成非线性运动的动画Tween
在被动画对象使用的数据范围之间进行插值。例如,Tween
可能会定义从红色到蓝色或从 0 到 255 的插值Listeners
和 StatusListeners
来监听动画状态的变化初始化一个 AnimationController
对象app
AnimationController controller = AnimationController(duration: const Duration(milliseconds: 500), vsync: this);
复制代码
初始化一个 Animation
对象, 并将 AnimationController
做为参数传递进去。这里的 Animation
对象是经过 Tween
对象的 animate
方法建立的ide
Animation<int> alpha = IntTween(begin: 0, end: 255).animate(controller);
复制代码
调用 AnimationController
的 forward()
方法执行动画动画
controller.forward();
复制代码
在 Widget
的 dispose()
方法中调用释放资源ui
controller.dispose();
复制代码
下面的案例是在给定的时间内改变 widget 的宽高this
Animation
的 value
来赋给 widget 的宽高setState(...)
来让 widget 重绘首先咱们须要一个能够改变状态的 widget
,也就是继承自 StatefulWidget
,而后按照咱们上述的步骤来,代码以下:spa
class AnimateApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _AnimateAppState();
}
}
class _AnimateAppState extends State<AnimateApp> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
@override
void initState() {
super.initState();
// 建立 AnimationController 对象
controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 2000));
// 经过 Tween 对象 建立 Animation 对象
animation = Tween(begin: 50.0, end: 200.0).animate(controller)
..addListener(() {
// 注意:这句不能少,不然 widget 不会重绘,也就看不到动画效果
setState(() {});
})
// 执行动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AnimateApp',
theme: ThemeData(
primaryColor: Colors.redAccent
),
home: Scaffold(
appBar: AppBar(
title: Text('AnimateApp'),
),
body: Center(
child: Container(
// 获取动画的值赋给 widget 的宽高
width: animation.value,
height: animation.value,
decoration: BoxDecoration(
color: Colors.redAccent
),
),
)
)
);
}
@override
void dispose() {
// 资源释放
controller.dispose();
super.dispose();
}
}
复制代码
效果以下:code
能够看出上面的动画是线性运动的,咱们能够经过 CurvedAnimation
来实现非线性运动的动画代码以下:cdn
controller = AnimationController(
vsync: this, duration: const Duration(milliseconds: 2000));
// 非线性动画
final CurvedAnimation curve = CurvedAnimation(
parent: controller, curve: Curves.elasticOut);
animation = Tween(begin: 50.0, end: 200.0).animate(curve)
..addListener(() {
setState(() {});
});
复制代码
效果以下:对象
而后咱们还能够给动画添加状态监听,经过给 Animation
添加 addStatusListener(...)
来监听当前动画的状态,如:动画是否播放完成。咱们能够给上面的例子加一个状态监听,让动画无限执行:
animation = Tween(begin: 50.0, end: 200.0).animate(curve)
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
复制代码
AnimationStatus.completed
表示动画在结束时中止的状态,这个时候咱们让动画反向执行(从后往前);AnimationStatus.dismissed
表示动画在开始时就中止的状态,这个时候咱们让动画正常执行(从前日后)。这样就可让动画无限执行了。
Tween
还能够接受 Color
类型的参数,实现颜色渐变的效果,下面让 widget 的颜色从 红色 渐变到 蓝色,部分代码以下:
controller = AnimationController(
duration: const Duration(milliseconds: 3000), vsync: this);
animation = ColorTween(begin: Colors.redAccent, end: Colors.blue).animate(
controller)
..addListener(() {
setState(() {});
});
controller.forward();
...
child: Container(
decoration: BoxDecoration(
color: animation.value
),
margin: EdgeInsets.symmetric(vertical: 10.0),
height: 200.0,
width: 200.0,
),
复制代码
效果以下:
咱们能够看到 _AnimateAppState
类后面跟了一个 with SingleTickerProviderStateMixin
,这个 with
什么意思呢 ? with
是 Dart 中的一个关键字,能够把它理解为 混入(mixin) 。能够看 stackoverflow 上的这个回答。
混入(mixin) 指的是能够将一个或多个类的功能添加到本身的类中,而无需继承这些类。混入后能够调用这些类中的方法。Dart 中没有多继承,可使用 混入(mixin)来避免多重继承会致使的问题。
上述代码中 _AnimateAppState
类 继承了 State
类,可是初始化 AnimationController
的时候须要一个 TickerProvider
类型的 vsync
参数,因此咱们 混入了 TickerProvider
的子类 SingleTickerProviderStateMixin
看一个简单的混入的小例子
void main() {
var a = new A();
a.methodB();
a.methodC();
a.methodD();
new E(a);
}
class A extends B with C, D {
}
class B {
void methodB() {
print('Class B methodB is call');
}
}
class C {
void methodC() {
print('Class C methodC is call');
}
}
class D {
void methodD() {
print('Class D methodD is call');
}
}
class E {
final C c;
E(this.c) {
c.methodC();
}
}
复制代码
能够看出类 A
继承了类 B
,而后 混入 了类 C
和类 D
,而后在 main
方法中可使用类 A
的实例去调用 类 B
, C
, D
中的方法。而后还有类 E
,构造方法中须要一个类 C
做为参数,而后由于类 A
混入了类 C
,因此能够把类 A
的实例看成参数传入到类 E
的构造方法中。
运行输出以下:
Class B methodB is call
Class C methodC is call
Class D methodD is call
Class C methodC is call
复制代码
在上面的例子中,咱们看到了这样的写法
animation = Tween(begin: 50.0, end: 200.0).animate(curve)
..addListener(() {
setState(() {});
});
复制代码
注意到 addListener
前面的两个点号 ..
了吧,什么意思呢?直接看个小例子吧!
void main() {
List<String> list = getList()
..add("android")
..add("flutter")
..add("kotlin")
..removeAt(0);
list.forEach((item) {
print(item);
});
// ----------等同于
print('---------------------------');
List<String> list2 = getList();
list2.add("android");
list2.add("flutter");
list2.add("kotlin");
list2.removeAt(0);
list2.forEach((item) {
print(item);
});
}
List<String> getList() {
return new List();
}
复制代码
输入以下:
flutter
kotlin
---------------------------
flutter
kotlin
复制代码
若有错误,还请指出,谢谢!