Tween是继承Animatable的,一般情况动画的取值范围都是(0.0,1.0),但是有些动画比如平移值、透明度、颜色值、大小值等,用(0.0,1.0)这个取值范围就不适用了。这时候就可以用Tween来指定范围。代码示例:
final Tween tween = Tween(begin:0.0,end:100.0);
Tween类是有一个泛型的,所以并不一定要是double类型。如果需要定义一个颜色变化的动画,可以通过ColorTween来实现,代码如下:
final Tween colorTween = ColorTween(begin:Colors.red,end:Colors.bule);
在动画的执行过程中,往往还需要获取动画的状态。但是Tween不会存储任何状态,需要调用evaluate()方法来获取动画的值。Tween还提供了animate()用于传入一个控制器对象。下面是使用Tween实现的一个放大–>缩小无线循环的动画:
import 'package:flutter/material.dart';
class TweenPage extends StatefulWidget {
final String title;
const TweenPage({Key? key, required this.title}) : super(key: key);
State<TweenPage> createState() => _TweenPageState();
}
class _TweenPageState extends State<TweenPage>
with SingleTickerProviderStateMixin {
Animation<double>? _animation;
AnimationController? _animationController;
void initState() {
super.initState();
_animationController =
AnimationController(duration: const Duration(seconds: 2), vsync: this);
_animation = Tween(begin: 0.0, end: 200.0).animate(_animationController!)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
_animationController!.reverse();
} else if (status == AnimationStatus.dismissed) {
_animationController!.forward();
}
})
..addListener(() {
setState(() {});
});
_animationController!.forward();
}
void dispose() {
_animationController!.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: SizedBox(
height: _animation!.value,
width: _animation!.value,
child: const FlutterLogo(),
),
),
);
}
}
上面的动画是线性的,那非线性的动画可以用Curve类来实现。
首先需要创建一个插值器,代码如下:
CurvedAnimation curvedAnimation = CurvedAnimation(parent:controller,curve:Curves.easeInOut);
CurvedAnimation与AnimationController都属于Animation类。而通过CurvedAnimation包装,就可以将Curves设置到Tween.animate()方法中,达到设置其运动曲线的目的。代码示例:
import 'package:flutter/material.dart';
class FreeFallPage extends StatefulWidget {
final String title;
const FreeFallPage({Key? key, required this.title}) : super(key: key);
State<FreeFallPage> createState() => _FreeFallPageState();
}
class _FreeFallPageState extends State<FreeFallPage>
with SingleTickerProviderStateMixin {
Animation<double>? _animation;
AnimationController? _animationController;
void initState() {
super.initState();
_animationController =
AnimationController(duration: const Duration(seconds: 5), vsync: this);
CurvedAnimation curvedAnimation =
CurvedAnimation(parent: _animationController!, curve: Curves.bounceOut);
_animation = Tween(begin: 0.0, end: 600.0).animate(curvedAnimation)
..addListener(() {
setState(() {});
});
_animationController!.forward();
}
void dispose() {
_animationController!.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(
children: [
Positioned(
left: MediaQuery.of(context).size.width / 2,
top: _animation!.value,
child: Container(
margin: const EdgeInsets.only(right: 10.0),
width: 20.0,
height: 20.0,
decoration: const BoxDecoration(
color: Colors.blue, shape: BoxShape.rectangle),
))
],
),
);
}
}