大家好,我是 17。
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,
));
void dispose() {
_controller.dispose();
super.dispose();
}
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) 开始的,那么点击位置可以设置在初始位置 。