【绘制 widget】Flutter FractionalTranslation

简介: 【绘制 widget】Flutter FractionalTranslation

image.png


大家好,我是 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

image.png

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 了。

目录
相关文章
|
缓存
【布局 widget】Flutter ListView
ListView 是最常用的滚动 widget,也是布局 widget。它在滚动方向上一个接一个地显示它的 child。
255 0
【布局 widget】Flutter ListView
【绘制 widget】Flutter DecratedBox
【绘制 widget】Flutter DecratedBox
141 0
【绘制 widget】Flutter DecratedBox
【布局 widget】Flutter LayoutBuilder
LayoutBuilder 构建一个依赖于 parent widget 大小的 widget tree。
154 0
【布局 widget】Flutter LayoutBuilder
【布局 Widget】 Flutter SizedBox
【布局 Widget】 Flutter SizedBox
112 0
【布局 Widget】 Flutter SizedBox
【布局 widget】Flutter CustomSingleChildLayout
【布局 widget】Flutter CustomSingleChildLayout
205 0
【布局 widget】Flutter CustomSingleChildLayout
|
容器
【布局 widget】 Flutter FractionallySizedBox
【布局 widget】 Flutter FractionallySizedBox
123 0
【布局 widget】 Flutter FractionallySizedBox
|
容器
【布局 widget】Flutter FittedBox
【布局 widget】Flutter FittedBox
183 0
【布局 widget】Flutter FittedBox
|
前端开发
【剪裁 widget】Flutter ClipRect
【剪裁 widget】Flutter ClipRect
116 0
【剪裁 widget】Flutter ClipRect
【动画 widget】Flutter AnimatedSize
【动画 widget】Flutter AnimatedSize
257 0
【动画 widget】Flutter AnimatedSize
【动画 widget】Flutter TweenAnimationBuilder
【动画 widget】Flutter TweenAnimationBuilder
172 0
【动画 widget】Flutter TweenAnimationBuilder