物理模拟能够让应用富有真实感和更好的交互性。例如,你可能会为一个 widget 添加动画,让它看起来就像安着弹簧,或是在随重力下落。
这个指南演示了如何将 widget 从拖动的点移回到中心,并使用弹簧模拟效果。
这个演示将进行下面几步:
- 创建一个动画控制器
- 使用手势移动 widget
- 对 widget 进行动画
- 计算速度以模拟弹跳运动
第一步:创建一个动画控制器
首先,创建一个叫做 DraggableCard
的 stateful widget:
让 _DraggableCardState
类继承至 SingleTickerProviderStateMixin。然后在 initState
中构造一个 AnimationController,并将其 vsync
属性设为 this
。
提示
继承的
SingleTickerProviderStateMixin
让 state 对象为AnimationController
提供了TickerProvider
的能力。要获得更多信息,请查看 TickerProvider 文档。
第二步:使用手势移动 widget
让 widget 可以被拖拽,并为 _DraggableCardState
类添加一个 Alignment 范围。
添加一个 GestureDetector 来捕获 onPanDown
、onPanUpdate
,以及 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/ 进行在线测试。