Flutter 中的 Animations(一)

@override
State createState() {
return _AnimateAppState();
}
}

class _AnimateAppState extends State with SingleTickerProviderStateMixin {

AnimationController controller;
Animation 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();
}
}

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以看出上面的动画是线性运动的,我们可以通过 CurvedAnimation 来实现非线性运动的动画代码如下:

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,
),

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

小提示

with

我们可以看到 _AnimateAppState 类后面跟了一个 with SingleTickerProviderStateMixin,这个 with 什么意思呢 ? withDart 中的一个关键字,可以把它理解为 混入(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

…addListener

在上面的例子中,我们看到了这样的写法

animation = Tween(begin: 50.0, end: 200.0).animate(curve)
…addListener(() {
setState(() {});
});

注意到 addListener 前面的两个点号 ..了吧,什么意思呢?直接看个小例子吧!

void main() {
List list = getList()
…add(“android”)
…add(“flutter”)
…add(“kotlin”)
…removeAt(0);

list.forEach((item) {
print(item);
});

// ----------等同于

print(‘---------------------------’);

List list2 = getList();
list2.add(“android”);
list2.add(“flutter”);
list2.add(“kotlin”);
list2.removeAt(0);

list2.forEach((item) {
print(item);
});
}
List getList() {
return new List();
}
输入如下:
flutter
;

List list2 = getList();
list2.add(“android”);
list2.add(“flutter”);
list2.add(“kotlin”);
list2.removeAt(0);

list2.forEach((item) {
print(item);
});
}
List getList() {
return new List();
}
输入如下:
flutter

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值