发表日期:2018-10 文章编辑:小灯 浏览次数:2601
你将学习到什么:
Terminology: 如果补间或补间的概念对您来说是新的,请参阅Flutter教程中的动画
交错的动画是一个直截了当的概念:视觉变化发生在一系列操作中,而不是一次性发生。 动画可能是纯粹顺序的,在下一个动画之后会发生一次更改,或者可能部分或完全重叠。 它也可能有间隙,没有发生变化。
本指南介绍了如何在Flutter中构建交错动画。
Examples
本指南介绍了basic_staggered_animation示例。您还可以参考更复杂的示例staggered_pic_selection。
basic_staggered_animation
显示单个窗口小部件的一系列连续和重叠动画。 点击屏幕会开始一个动画,可以改变不透明度,大小,形状,颜色和填充。
staggered_pic_selection
显示从以三种尺寸之一显示的图像列表中删除图像。此示例使用两个动画控制器: 一个用于图像选择/取消选择,另一个用于图像删除。 选择/取消选择动画是错开的。 (要查看此效果,您可能需要增加timeDilation
值。) 选择一个最大的图像,它会缩小,因为它在蓝色圆圈内显示一个复选标记。 接下来,选择一个最小的图像,当复选标记消失时,大图像会扩展。 在大图像完成展开之前,小图像会缩小以显示其复选标记。 这种交错行为类似于您在Google相册中看到的行为。
以下视频演示了basic_staggered_animation执行的动画:
在视频中,您会看到单个小部件的以下动画,该小部件以带有略微圆角的边框蓝色方块开始。 该方块按以下顺序运行更改:
向前跑之后,动画反向运行。
Flutter新手?
本页假定您知道如何使用Flutter的小部件创建布局。 有关更多信息,请参阅在Flutter中构建布局.
重点是什么?
下图显示了basic_staggered_animation示例中使用的间隔。 您可能会注意到以下特征:
要设置动画:
animate
方法需要parent
控制器,并为该属性生成一个Animation。curve
属性上指定间隔。当控制动画的值更改时,新动画的值会更改,从而触发UI更新。
以下代码为width
属性创建补间。 它构建一个CurvedAnimation ,指定一个缓和的曲线。 有关其他可用的预定义动画曲线,请参阅曲线。
width = Tween<double>( begin: 50.0, end: 150.0, ).animate( CurvedAnimation( parent: controller, curve: Interval( 0.125, 0.250, curve: Curves.ease, ), ), ),
begin
和 end
的值不必是双倍的。下面的代码使用BorderRadius.circular()
为borderRadius
属性(控制方块角的圆度)构建补间。
borderRadius = BorderRadiusTween( begin: BorderRadius.circular(4.0), end: BorderRadius.circular(75.0), ).animate( CurvedAnimation( parent: controller, curve: Interval( 0.375, 0.500, curve: Curves.ease, ), ), ),
与所有交互式小部件一样,完整的动画由小部件对组成:无状态小部件和有状态小部件。
无状态窗口小部件指定补间,定义Animation对象,并提供build()
函数,负责构建窗口小部件树的动画部分。
有状态小部件创建控制器,播放动画,并构建小部件树的非动画部分。 在屏幕中的任何位置检测到点击时,动画开始。
basic_staggered_animation’s main.dart的完整代码
在无状态小部件StaggerAnimation中, build()
函数实例化一个AnimatedBuilder - 一个用于构建动画的通用小部件。 AnimatedBuilder构建一个小部件并使用Tweens的当前值配置它。 该示例创建一个名为_buildAnimation()
的函数(执行实际的UI更新),并将其分配给其builder
属性。 AnimatedBuilder监听来自动画控制器的通知,在值发生变化时将小部件树标记为脏。 对于动画的每个刻度,值都会更新,从而调用_buildAnimation()
。
class StaggerAnimation extends StatelessWidget { StaggerAnimation({ Key key, this.controller }) :// Each animation defined here transforms its value during the subset // of the controller's duration defined by the animation's interval. // For example the opacity animation transforms its value during // the first 10% of the controller's duration.opacity = Tween<double>( begin: 0.0, end: 1.0, ).animate( CurvedAnimation( parent: controller, curve: Interval( 0.0, 0.100, curve: Curves.ease, ), ), ),// ... Other tween definitions ...super(key: key);final Animation<double> controller; final Animation<double> opacity; final Animation<double> width; final Animation<double> height; final Animation<EdgeInsets> padding; final Animation<BorderRadius> borderRadius; final Animation<Color> color;// This function is called each time the controller "ticks" a new frame. // When it runs, all of the animation's values will have been // updated to reflect the controller's current value. Widget _buildAnimation(BuildContext context, Widget child) { return Container( padding: padding.value, alignment: Alignment.bottomCenter, child: Opacity( opacity: opacity.value, child: Container( width: width.value, height: height.value, decoration: BoxDecoration( color: color.value, border: Border.all( color: Colors.indigo[300], width: 3.0, ), borderRadius: borderRadius.value, ), ), ), ); }@override Widget build(BuildContext context) { return AnimatedBuilder( builder: _buildAnimation, animation: controller, ); } }
有状态小部件StaggerDemo创建了AnimationController(规定他们的对象),指定持续时间为2000毫秒。 它播放动画,并构建小部件树的非动画部分。 在屏幕中检测到点击时动画开始。 动画向前,然后向后。
class StaggerDemo extends StatefulWidget { @override _StaggerDemoState createState() => _StaggerDemoState(); }class _StaggerDemoState extends State<StaggerDemo> with TickerProviderStateMixin { AnimationController _controller;@override void initState() { super.initState();_controller = AnimationController( duration: const Duration(milliseconds: 2000), vsync: this ); }// ...Boilerplate...Future<Null> _playAnimation() async { try { await _controller.forward().orCancel; await _controller.reverse().orCancel; } on TickerCanceled { // the animation got canceled, probably because we were disposed } }@override Widget build(BuildContext context) { timeDilation = 10.0; // 1.0 is normal animation speed. return Scaffold( appBar: AppBar( title: const Text('Staggered Animation'), ), body: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { _playAnimation(); }, child: Center( child: Container( width: 300.0, height: 300.0, decoration: BoxDecoration( color: Colors.black.withOpacity(0.1), border: Border.all( color:Colors.black.withOpacity(0.5), ), ), child: StaggerAnimation( controller: _controller.view ), ), ), ), ); } }
编写动画时,以下资源可能会有所帮助:
Animations landing page
列出Flutter动画的可用文档。 如果补间对您来说不熟悉,请查看动画教程 。
Flutter API documentation
所有Flutter库的参考文档。 特别是,请参阅动画库文档。
Flutter Gallery
演示应用程序展示了许多材料组件和其他Flutter功能。 Shrine demo实现了英雄动画。
Material motion spec
描述材料应用的动作。
日期:2018-10 浏览次数:7246
日期:2018-12 浏览次数:4319
日期:2018-07 浏览次数:4868
日期:2018-12 浏览次数:4168
日期:2018-09 浏览次数:5490
日期:2018-12 浏览次数:9915
日期:2018-11 浏览次数:4797
日期:2018-07 浏览次数:4573
日期:2018-05 浏览次数:4851
日期:2018-12 浏览次数:4315
日期:2018-10 浏览次数:5132
日期:2018-12 浏览次数:6206
日期:2018-11 浏览次数:4453
日期:2018-08 浏览次数:4585
日期:2018-11 浏览次数:12622
日期:2018-09 浏览次数:5570
日期:2018-12 浏览次数:4823
日期:2018-10 浏览次数:4178
日期:2018-11 浏览次数:4522
日期:2018-12 浏览次数:6057
日期:2018-06 浏览次数:4002
日期:2018-08 浏览次数:5427
日期:2018-10 浏览次数:4452
日期:2018-12 浏览次数:4516
日期:2018-07 浏览次数:4355
日期:2018-12 浏览次数:4493
日期:2018-06 浏览次数:4375
日期:2018-11 浏览次数:4369
日期:2018-12 浏览次数:4242
日期:2018-12 浏览次数:5275
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.