Flutter中的基本动画
虽然 Flutter 有大量用于为您的应用程序创建动画效果的令人惊叹的包,但也有用于手动创建更精细动画的内置方法。
先决条件
对于我们的跨屏动画,我假设您已经知道如何创建基本路线,只是为了保持简短。 如果您对此不满意,可以在此处查看 文档 。
线性动画
我们动画的主要三个部分是 ticker
来控制我们的时间,controller
来注册我们的参数,比如我们的持续时间,然后我们想要更改的值。 在我们的小部件被渲染之前,在我们的 initState
中,我们可以将我们的控制器设置为它的参数,设置它的方向,并添加一个侦听器来在每次更改时重置我们的小部件状态。
默认情况下,控制器会在我们设置的持续时间内将变化从 0 移动到 1,我们可以在监听器中打印 controller.value
来观察这种情况。 我们可以通过设置 upperBound
或 lowerBound
属性来更改我们的默认开始和结束值。
主要.dart
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(() {})); } }
要使用我们的动画,我们只需将我们想要的任何内容(例如不透明度)设置为 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), ), ), ); }
曲线动画
我们可以使用不同的曲线变化来精确控制控制器的变化方式,而不是无聊的线性动画。 为此,我们可以使用 CurvedAnimation
在我们原来的控制器上创建一种包装器。 这个包装器将采用它的父级、我们的控制器和我们想要应用的曲线。 当使用弯曲动画时,除了 0 和 1 之外,我们不能有下限和上限,所以当我们应用它时,我们可以乘以它的值。 在 文档 中有一个非常广泛的选项列表。
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), ), ); } }
补间
除了使用数字值之外,我们还可以使用补间(介于之间的缩写)来处理其他事物的范围,例如颜色。 就像我们的曲线动画一样,它将充当控制器或动画的包装器,我们可以将颜色设置为其值。
主要.dart
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), ), ); } }
十字屏
当我们想要在不同屏幕上的小部件之间进行转换时,另一个很棒的技术是使用 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() ]), ); }
结论
在过去的大多数前端 Web 技术中,动画都是事后才想到的,但 Flutter 团队在开发这个令人惊叹的框架时在牢记动画方面做得非常出色。 我们实际上只是触及了 Flutter 在动画方面的能力的皮毛。