flutter中的动画效果
While Flutter has an enormous amount of amazing packages for creating animation effects for your apps, there are also built-in methods for manually creating more fine-tuned animations.
尽管Flutter提供了大量令人惊叹的软件包,可为您的应用创建动画效果,但也有内置方法可用于手动创建更多微调的动画。
For our cross-screen animations I’ll be assuming that you already know how to create basic routes, just to keep things brief. You can review the docs here if you’re not comfortable with that just yet.
对于我们的跨屏动画,我假设您已经知道如何创建基本路线,只是为了使内容简短。 如果您还不满意,可以在这里查看文档 。
The main three parts of our animations are the ticker
to control our time, the controller
to register our parameters like our duration, and then the values we want changed. Before our widget is rendered, in our initState
, we can set our controller to its parameters, set its direction, and add a listener to reset our widgets state with every change.
动画的主要三个部分是控制时间的ticker
,用于注册诸如持续时间之类的参数的controller
,然后是我们想要更改的值。 在呈现窗口小部件之前,可以在initState
控制器设置为其参数,设置其方向,并添加一个侦听器以在每次更改时重置窗口小部件的状态。
By default a controller will move change from 0 to 1 in the time we set for our duration, we can print our controller.value
in our listener to watch this happen. We can change our default start and end values by setting the upperBound
or lowerBound
properties.
默认情况下,控制器会在我们为持续时间设置的时间内将更改从0移动到1,我们可以在监听controller.value
中打印controller.value
来观察这种情况。 我们可以通过设置upperBound
或lowerBound
属性来更改默认的开始值和结束值。
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this); // Links this controller to this widget so it won't run if the parent widget isn't rendered, to save on resources.
controller.forward();
controller.addListener(() => setState(() {}));
}
}
To use our animation we just need to set whatever we want, like opacity, to controller.value
.
要使用动画,我们只需要将所需的内容(如不透明度)设置为controller.value
。
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Opacity(
opacity: controller.value,
child: Container(width: 50, height: 50, color: Colors.red),
),
),
);
}
Instead of boring linear animations we can use different curved variations to control exactly how our controller changes. To do this we can user CurvedAnimation
to create a kind of wrapper over our original controller. This wrapper will take its parent, our controller, and the curve we want to apply. When using a curved animation we can’t have lower and upper bounds besides 0 and 1, so when we apply it we can just multiply its value. There’s a really extensive list of options over in the docs.
代替无聊的线性动画,我们可以使用不同的曲线变化来精确控制控制器的变化方式。 为此,我们可以使用CurvedAnimation
在原始控制器上创建一种包装器。 该包装器将使用其父级,控制器和我们要应用的曲线。 使用弯曲动画时,除0和1外,不能有上限和下限,因此应用它时,我们可以将其值相乘。 在docs中有很多选项。
Another useful method on controller
is addStatusListener
, which will allow us to tap into its lifecycle. Our controller triggers a completed or dismissed event whenever it’s value has reached its upper or lower bound. We can use this with its forward
and reverse
methods to loop our animation infinitely.
controller
上的另一个有用方法是addStatusListener
,它使我们能够利用其生命周期。 每当其值达到其上限或下限时,我们的控制器就会触发一个完成或被取消的事件。 我们可以使用它的forward
和reverse
方法无限循环播放动画。
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this);
animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);
controller.forward();
animation.addListener(() => setState(() {}));
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) controller.reverse(from: 400);
else if (status == AnimationStatus.dismissed) controller.forward();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.only(bottom: animation.value * 400),
width: 50,
height: 50,
color: Colors.red),
),
);
}
}
Instead of just working with number values, we can also work with ranges of other things, like colors, using tweens (short for between). Like with our curved animation, it will act as a wrapper for our controller or animation and we can set our color to its value.
我们不仅可以使用数字值,还可以使用补间(tweens)来处理其他范围,例如颜色。 与弯曲动画一样,它将用作控制器或动画的包装,我们可以将颜色设置为其值。
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
Animation changeColor;
void initState() {
super.initState();
controller =
AnimationController(duration: Duration(seconds: 1), vsync: this);
animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);
changeColor = ColorTween(begin: Colors.red, end: Colors.blue).animate(animation);
controller.forward();
animation.addListener(() => setState(() {}));
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) controller.reverse(from: 400);
else if (status == AnimationStatus.dismissed) controller.forward();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.only(bottom: animation.value * 400),
width: 50,
height: 50,
color: changeColor.value),
),
);
}
}
Another awesome technique is to use the Hero widget when we want a transition between widgets on different screens. We just need to wrap each in its own Hero widget with matching tags. The tags must be unique and there cannot be more than one on the screen at any time.
另一个很棒的技术是当我们想要在不同屏幕上的小部件之间进行转换时使用Hero小部件。 我们只需要使用匹配的标签将它们包装在自己的Hero小部件中即可。 标签必须唯一,并且屏幕上任何时候都不能超过一个。
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Hero(tag: 'icon', child: Icon(Icons.add)),
]),
Navbar()
]));
}
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SizedBox(width: 1),
Hero(
tag: 'icon',
child: Icon(Icons.add, color: Colors.red, size: 75)),
]),
Navbar()
]),
);
}
With most frontend web technologies from the past, animations were left as an after-thought, but the flutter team did an amazing job at keeping animations in mind when developing this amazing framework. We really only scratched the surface of what Flutter is capable of in terms of animations.
在过去使用大多数前端Web技术的情况下,动画是事后才想到的,但是在开发这个令人惊叹的框架时,颤抖的团队在将动画铭记在心方面做得非常出色。 我们真的只是从动画的角度介绍了Flutter的功能。
翻译自: https://www.digitalocean.com/community/tutorials/flutter-animations-in-flutter
flutter中的动画效果