Widget的物理模拟动画效果

物理模拟能够让应用富有真实感和更好的交互性。例如,你可能会为一个 widget 添加动画,让它看起来就像安着弹簧,或是在随重力下落。

这个指南演示了如何将 widget 从拖动的点移回到中心,并使用弹簧模拟效果。

这个演示将进行下面几步:

  1. 创建一个动画控制器
  2. 使用手势移动 widget
  3. 对 widget 进行动画
  4. 计算速度以模拟弹跳运动

第一步:创建一个动画控制器

首先,创建一个叫做 DraggableCard 的 stateful widget:

让 _DraggableCardState 类继承至 SingleTickerProviderStateMixin。然后在 initState 中构造一个 AnimationController,并将其 vsync 属性设为 this

提示

继承的 SingleTickerProviderStateMixin 让 state 对象为 AnimationController 提供了 TickerProvider 的能力。要获得更多信息,请查看 TickerProvider 文档。

第二步:使用手势移动 widget

让 widget 可以被拖拽,并为 _DraggableCardState 类添加一个 Alignment 范围。

添加一个 GestureDetector 来捕获 onPanDownonPanUpdate,以及 onPanEnd 回调。为了调整对齐方式,请使用 MediaQuery 来获得 widget 的大小,然后除以 2。(这会将「拖动的像素」单位转为 Align 使用的坐标。)然后,将 Align widget 的 alignmnt 属性设为 _dragAlignment

第三步:对 widget 进行动画

当一个 widget 被释放,它应该就会弹回中心。

添加一个 Animation<Alignment>,以及 _runAnimation 方法。此方法定义了一个 Tween,它在 widget 被拖动到的点之间插入到中心点。

接下来,当 AnimationController 产生一个值时,更新 _dragAlignment

下一步,让 Align widget 使用 _dragAlignment 字段:

最后,更新 GestureDetector 来管理动画控制器:

第四步:计算速度以模拟弹跳运动

最后一步时做一些简单的数学计算,计算小部件被拖动完成之后的速度。这样小部件在被快速恢复之前实际上以该速度继续运动。(_runAnimation 方法已经通过设置动画的开始和结束对齐方式来设置方向。)

首先,引入 physics 这个 package:

onPanEnd 回调提供了一个 DragEndDetails 对象。此对象提供指针停止接触屏幕时的速度。速度以每秒像素为单位,但 Align widget 不使用像素。它使用 [-1.0,-1.0] 和 [1.0,1.0] 之间的坐标值,其中 [0.0,0.0] 表示中心。在步骤 2 中计算的 size 用于将像素转换为该范围内的坐标值。

最后,AnimationController 有一个 animateWith() 方法可以产生 SpringSimulation:

不要忘记调用 _runAnimation(),并传入速度和大小:

提示

既然动画控制器使用了模拟,就不再需要指定 duration 参数。

交互式样例

上述代码可以在 https://www.dartpad.dev/ 进行在线测试。

参考链接


Widget 的物理模拟动画效果

发布者

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注