大家好,我是 17。今天的每日 widget 为大家介绍 FractionalTranslation。
FractionalTranslation 可以按比例偏移 child,在 Animation 的加持下,可以实现直线滑动的动画效果,比如 SlideTransition 就是这样实现的动画效果。
FractionalTranslation 介绍
FractionalTranslation 继承自 SingleChildRenderObjectWidget。renderObject 是 RenderFractionalTranslation 类的实例。RenderFractionalTranslation extends RenderProxyBox
没有 override PerformLayout 方法,所以布局方面没有什么建树。 如果有 child,透传 Constrains 给 child,size 和 child 一样大。他的能力是在绘制阶段完成的。
源码分析
@override void paint(PaintingContext context, Offset offset) { assert(!debugNeedsLayout); if (child != null) { super.paint( context, Offset( offset.dx + translation.dx * size.width, offset.dy + translation.dy * size.height, )); } } 复制代码
逻辑还是很简单的,就是绘制的时候在 x 轴方向加上偏移 translation.dx * size.width
,在 y 轴方向加上偏移 translation.dy * size.height
@override bool hitTest(BoxHitTestResult result, {required Offset position}) { return hitTestChildren(result, position: position); } @override bool hitTestChildren(BoxHitTestResult result, {required Offset position}) { assert(!debugNeedsLayout); return result.addWithPaintOffset( offset: transformHitTests ? Offset(translation.dx * size.width, translation.dy * size.height) : null, position: position, hitTest: (BoxHitTestResult result, Offset position) { return super.hitTestChildren(result, position: position); }, ); } 复制代码
FractionalTranslation 能否通过点击测试完全取决于 child。
transformHitTests 为 false,点击 child 溢出的部分不会通过 hitTest。
transformHitTests 为 true,对 dx,dy 做了偏移,抵消掉了绘制的时候 child 偏移的影响。 点击 child 溢出的部分会通过 hitTest。
使用 FractionalTranslation
Center( child: Container( foregroundDecoration: BoxDecoration(border: Border.all(color: Colors.red)), child: FractionalTranslation( transformHitTests: true, translation: Offset(0.5, 0), child: GestureDetector( onPanDown: (details) { print( '${details.globalPosition}--${details.localPosition}'); }, child: Container( width: 100, height: 100, color: Colors.blue, )), ))); 复制代码
红色部分是 FractionalTranslation 的 size,大小为 Size(100,100),参数 Offset(0.5, 0) 让 child 向右偏移 100*0.5= 50
。偏移的值也可以为负,比如 Offset(-0.5, 0) 就会向左偏移 50。
虽然在视觉上 child 超出右边 50,但是所占的位置 在 layout 阶段就已经确定了,所以无论 child 如何偏移,FractionalTranslation 所占的位置都是红框部分。
参数 transformHitTests 会影响到 localPosition 。如果为 true(默认值)localPosition 的值是相对于 child 的左上角的。否则相对于 FractionalTranslation 的左上角。transformHitTests 对 globalPosition 没有影响。
关于点击范围
FractionalTranslation size 内的 child 是可以点击的,只要父级的 size 都包含了 child。溢出的部分能否点击取决于父级的 size 是多大 并且 FractionalTranslation 的参数 transformHitTests: true
。只要所有的父级都包含了 child 溢出的部分,溢出的部分也是可以点击的。因为点击测试是从顶层向下层发起的,进行深度优先遍历,如果pointerEvent 在上层某个 widget 的 size 之外,那么在上层就不会再调用 child 的 hitTest,下面的 children 就没有机会参加 hitTest,当然也就没有机会通过 hitTest 了。