SlideTransition 根据位置的变化产生动画效果的 widget。一些 widget 是以 SlideTransition 为基础做的动画效果,所以 SlideTransition 是一个很重要的动画 widget。
SlideTransition 介绍
SlideTransition 继承自 AnimatedWidget, 位置的变化是由 FractionalTranslation 实现的。参数 Offset(dx,dy) 的 dx,dy 是一个比例值。
和 FractionalTranslation 一样,位置在布局阶段就已经定好了。要想控制显示范围,可以用 ClipRect
使用 SlideTransition
const SlideTransition({ super.key, required Animation<Offset> position, this.transformHitTests = true, this.textDirection, this.child, }) 复制代码
- position 位置的比例系数。比如 0.5 表示向右偏移 width 的 50%。
- transformHitTests 默认为 true。作用是否对 pointerEvent 的 position 进行转换
final Offset transformedPosition = offset == null ? position : position - offset; 复制代码
转换的结果是把绘制时的偏移减掉,相当于消除了偏移造成的影响,所以 child hitTest 通过。整个区域都可以响应点击。transformHitTests 如果为 false,溢出的部分无法通过 hitTest,因为 pointerEvent 的 position 在 child size 的范围之外。
- textDirection 这个不用管,我们一般都是从左到右。
实例
class _MyStatefulWidgetState extends State<MyStatefulWidget> with SingleTickerProviderStateMixin { late final AnimationController _controller = AnimationController( duration: const Duration(seconds: 2), vsync: this, )..repeat(reverse: true); late final Animation<Offset> _offsetAnimation = Tween<Offset>( begin: const Offset(-1, -1.0), end: const Offset(1, 1.0), ).animate(CurvedAnimation( parent: _controller, curve: Curves.elasticIn, )); @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return SlideTransition( position: _offsetAnimation, child: const Padding( padding: EdgeInsets.all(8.0), child: FlutterLogo(size: 150.0), ), ); } } 复制代码
本例的动画轨迹是一条从左上到右下的斜直线。实际上 SlideTransition 只能沿直线运动。如果想让 SlideTransition child 在运动的时候都能响应点击,除了保证 transformHitTests true 外,还需要所有父级都包含了 child 整个运动轨迹。
SlideTransition 用户体验的思考
ransformHitTests 默认是 true 的,如果动画很慢,用户可以准确点击到 child 中的位置。但是如果动画很快,那么用户是很难点中 child 中的位置的,而且响应的时候 child 可能已经到其它位置了。这个时候最好 将 ransformHitTests 设置为 false。只允许用户点击 child 的最终位置。如果动画只有一次,那么最终位置已经停止了。如果是重复动画,也没有问题,因为无论 child 在哪里,只要点这个位置都可以成功。
最终位置是指 position(0,0)。
如果动画是从 position(0,0) 开始的,那么点击位置可以设置在初始位置 。