今天对Flutter动画进行一次突击,这篇文章是我对Flutter动画的使用和理解,有可能有不对的地方,欢迎大家给我指正
final AnimationController controller = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
AnimationController派生自Animation,因此可以在需要Animation对象的任何地方使用。 但是,AnimationController具有控制动画的其他方法。例如,.forward()方法可以启动动画。数字的产生与屏幕刷新有关,因此每秒钟通常会产生60个数字,在生成每个数字后,每个Animation对象调用添加的Listener对象。
当创建一个AnimationController时,需要传递一个vsync
参数,存在vsync
时会防止屏幕外动画(译者语:动画的UI不在当前屏幕时)消耗不必要的资源。 通过将SingleTickerProviderStateMixin
添加到类定义中,可以将stateful对象作为vsync
的值。
final CurvedAnimation curve =
new CurvedAnimation(parent: controller, curve: Curves.easeIn);
final Tween doubleTween = new Tween(begin: -200.0, end: 0.0);
Tween对象不存储任何状态。相反,它提供了evaluate(Animation
方法将映射函数应用于动画当前值。 Animation对象的当前值可以通过value()方法取到。evaluate函数还执行一些其它处理,例如分别确保在动画值为0.0和1.0时返回开始和结束状态。
Tween.animate
要使用Tween对象,请调用其animate()方法,传入一个控制器对象。例如,以下代码在500毫秒内生成从0到255的整数值。
final AnimationController controller = new AnimationController(
duration: const Duration(milliseconds: 500), vsync: this);
Animation alpha = new IntTween(begin: 0, end: 255).animate(controller);
注意animate()
返回的是一个Animation,而不是一个Animatable。
以下示例构建了一个控制器、一条曲线和一个Tween:
final AnimationController controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
final Animation animation = CurvedAnimation(parent: controller,curve: Curves.easeInOutQuart)
Animation alpha = new IntTween(begin: 0, end: 255).animate(animation);
addListener()
和addStatusListener()
来添加。 只要动画的值发生变化,就会调用监听器。一个Listener最常见的行为是调用setState()来触发UI重建。动画开始、结束、向前移动或向后移动(如AnimationStatus所定义)时会调用StatusListener。 下一节中有一个addListener()
方法的例子。监视动画的进度展示了如何调用addStatusListener()
。addListener()
我们必须手动执行setState()
来刷新UI界面import 'package:flutter/material.dart';
class CurvedAnimationPage extends StatefulWidget {
final String title;
CurvedAnimationPage({Key key, this.title}) : super(key: key);
@override
_CurvedAnimationPageState createState() => _CurvedAnimationPageState();
}
class _CurvedAnimationPageState extends State
with SingleTickerProviderStateMixin {
Animation animation;
AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = Tween(begin: 0.0, end: 300.0).animate(controller)
..addListener(() {
setState(() {
// animation.value;
});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('曲线动画'),
),
body: Container(
width: animation.value,
height: animation.value,
child: FlutterLogo(),
));
}
}
AnimatedWidget
来创建动画这里不需要手动修改setState()
import 'package:flutter/material.dart';
class CurvedAnimationPage extends StatefulWidget {
final String title;
CurvedAnimationPage({Key key, this.title}) : super(key: key);
@override
_CurvedAnimationPageState createState() => _CurvedAnimationPageState();
}
class _CurvedAnimationPageState extends State
with SingleTickerProviderStateMixin {
Animation animation;
AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = CurvedAnimation(parent: controller,curve: Curves.easeInOutQuart)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedLogo(animation: animation,);
}
}
// AnimatedWidget 的使用
class AnimatedLogo extends AnimatedWidget {
static final _opacityTween = Tween(begin: 0.1, end: 1);
static final _sizeTween = Tween(begin: 0.0, end: 300);
AnimatedLogo({Key key, Animation animation}):super(key:key,listenable:animation);
@override
Widget build(BuildContext context) {
final Animation animation = listenable;
return Scaffold(
appBar: AppBar(
title: Text(
"曲线动画",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
// centerTitle: false,
),
body: Center(
child: Opacity(
opacity: _opacityTween.evaluate(animation),
child: Container(
width: _sizeTween.evaluate(animation),
height: _sizeTween.evaluate(animation),
child: FlutterLogo(),
),
),
));
}
}
AnimatedBuilder
创建动画import 'package:flutter/material.dart';
class CurvedAnimationPage extends StatefulWidget {
final String title;
CurvedAnimationPage({Key key, this.title}) : super(key: key);
@override
_CurvedAnimationPageState createState() => _CurvedAnimationPageState();
}
class _CurvedAnimationPageState extends State
with SingleTickerProviderStateMixin {
Animation animation;
AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = CurvedAnimation(parent: controller,curve: Curves.easeInOutQuart)
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});
controller.forward();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('曲线动画d'),
),
body: GrowTransition(child: LogoWidget(),animation: animation)
);
}
}
// AnimatedBuilder 的使用
class GrowTransition extends StatelessWidget {
final Widget child;
final Animation animation;
static final _opacityTween = Tween(begin: 0.1, end: 1);
static final _sizeTween = Tween(begin: 0.0, end: 300);
const GrowTransition({Key key,this.child,this.animation}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
animation: animation,
child: child,
builder: (BuildContext context, Widget child) {
return Opacity(
opacity: _opacityTween.evaluate(animation),
child: Container(
width: _sizeTween.evaluate(animation),
height: _sizeTween.evaluate(animation),
child: child,
),
);
},
),
);
}
}
class LogoWidget extends StatelessWidget {
const LogoWidget({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child:Container(
child: FlutterLogo(),
)
);
}
}
return RotationTransition(
turns:Tween(begin:0.0,end:1.0)
.animate(CurvedAnimation(
parent: animation1,
curve: Curves.fastOutSlowIn
)),
child:ScaleTransition(
scale:Tween(begin: 0.0,end:1.0)
.animate(CurvedAnimation(
parent: animation1,
curve:Curves.fastOutSlowIn
)),
child: child,
)
);
return FadeTransition(
opacity: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
parent: animation1,
curve: Curves.fastOutSlowIn)
),
child: child,
);
return SlideTransition(
position: Tween(
begin: Offset(1.0, 0.0),
end: Offset(0.0, 0.0)
).animate(CurvedAnimation(
parent: animation1,
curve: Curves.fastOutSlowIn
)),
child: child,
);