AnimationController
在 Flutter 中,我们基本上有两种类型的动画:隐式和显式。隐式动画是 Fluter SDK 中可用的预构建动画,显式动画需要一个controller
来执行动画。其构造函数:
AnimationController({
double? value,
this.duration,
this.reverseDuration,
this.debugLabel,
this.lowerBound = 0.0,//区间
this.upperBound = 1.0,//区间
this.animationBehavior = AnimationBehavior.normal,
required TickerProvider vsync,//TickerProvider类型,必须添加SingleTickerProviderStateMixin
})
AnimationController
提供了很多方法:
forward
: 动画将从lowerBound到upperBound。reverse
: 动画将从upperBound到lowerBound。repeat
: 动画将从lowerBound到upperBound和从upperBound到重复loweBound。stop
:动画将停止运行。reset
: 动画会回到初始状态。AnimationController
会在动画的每一帧,就会生成一个新的值。默认情况下,AnimationController
在给定的时间段内线性的生成从 0.0 到1.0(默认区间)的数字。
创建了一个Animation对象
final controller = AnimationController(
duration: const Duration(seconds: 2),
//生成数字的区间可以通过lowerBound和upperBound来指定
lowerBound: 10.0,
upperBound: 20.0,
vsync: vsync
);
创建AnimationController
时,需要传递一个vsync
参数,vsync
参数可防止屏幕外动画消耗不必要的资源。我们可以将SingleTickerProviderStateMixin
添加到State
的定义中,然后将State
对象作为vsync
的值。下面我们来举个例子
添加SingleTickerProviderStateMixin
class _AnimationPageState extends State<AnimationPage> with SingleTickerProviderStateMixin{
...
}
定义一个 AnimationController
class _AnimationPageState extends State<AnimationPage> with SingleTickerProviderStateMixin{
late AnimationController _controller;
}
实例化创建这个_controller 的方法
@override
void initState() {
// TODO: implement initState
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
}
以上,我们通过两个参数来实例化类
duration
:这是此动画应持续的总时间长度。vsync
: 一个TickerProvider
是必需的。因此,我们必须用SingleTickerProviderMixin
。 在这种情况下,值this
仅指类的 current context。
构建页面UI
import 'package:flutter/material.dart';
class AnimationPage extends StatefulWidget {
const AnimationPage({Key? key}) : super(key: key);
@override
State<AnimationPage> createState() => _AnimationPageState();
}
class _AnimationPageState extends State<AnimationPage> with SingleTickerProviderStateMixin{
late AnimationController _controller;
@override
void initState() {
// TODO: implement initState
super.initState();
//创建动画控制器
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Animation'),),
body: Stack(
children: [
Image.asset(
'images/qiuc.jpeg',
fit: BoxFit.cover,
height: double.infinity,
width: double.infinity,
),
Transform.translate(
offset: const Offset(250,300),
child: Image.asset(
'images/qiu.png',
fit: BoxFit.contain,
height: 70,
width: 70,
),
)
],
),
);
}
}
现在要从上到下和从下到上移动篮球,为此,我们需要调用repeat方法,并且需要更新球的偏移量。
完整代码:
import 'package:flutter/material.dart';
class AnimationPage extends StatefulWidget {
const AnimationPage({Key? key}) : super(key: key);
@override
State<AnimationPage> createState() => _AnimationPageState();
}
class _AnimationPageState extends State<AnimationPage> with SingleTickerProviderStateMixin{
late AnimationController _controller;
@override
void initState() {
// TODO: implement initState
super.initState();
//创建动画控制器
_controller = AnimationController(
duration: const Duration(milliseconds: 500),
vsync: this,
upperBound: 650,
lowerBound: 400,
);
//添加动画执行刷新监听
_controller.addListener(() {
setState(() {
});
});
//调用repeat方法
_controller.repeat(reverse: true);
}
@override
void dispose() {
// TODO: implement dispose
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Animation'),),
body: Stack(
children: [
Image.asset(
'images/qiuc.jpeg',
fit: BoxFit.cover,
height: double.infinity,
width: double.infinity,
),
Transform.translate(
offset: Offset(250,_controller.value),//改变y的偏移量
child: Image.asset(
'images/qiu.png',
fit: BoxFit.contain,
height: 70,
width: 70,
),
)
],
),
);
}
}
效果: