重写 RenderStack 改变Stack children 处理手势的顺序

141 阅读1分钟
class _ThroughStack extends Stack {
  const _ThroughStack({required super.children});

  @override
  _ThroughRenderStack createRenderObject(BuildContext context) {
    return _ThroughRenderStack(
      alignment: alignment,
      textDirection: textDirection ?? Directionality.of(context),
      fit: fit,
    );
  }
}


class _ThroughRenderStack extends RenderStack {
  _ThroughRenderStack({
    required super.alignment,
    super.textDirection,
    required super.fit,
  });

  @override
  bool hitTestChildren(BoxHitTestResult result, {Offset? position}) {
    bool stackHit = false;

    final List<RenderBox> children = getChildrenAsList();

    for (final RenderBox child in children) {
      final StackParentData childParentData =
      child.parentData as StackParentData;

      final bool childHit = result.addWithPaintOffset(
        offset: childParentData.offset,
        position: position!,
        hitTest: (BoxHitTestResult result, Offset transformed) {
          assert(transformed == position - childParentData.offset);
          return child.hitTest(result, position: transformed);
        },
      );
      if (childHit) {
        stackHit = true;
      }
    }

    return stackHit;
  }
}

默认stack 是从最顶上的child开始响应手势。

使用

 _ThroughStack(
  children: [
   
    ...["1","2","3"].map((item)=>GestureDetector(
      onTap: (){
        debugPrint("=====onTap===$item");
      },
      child: Container(
        width: 100,
        height: 100,
        color: Colors.green,
        alignment: Alignment.center,
        child: Text(item,style: const TextStyle(
            fontSize: 16,
            color: Colors.black
        ),),
      ),
    )).toList(),
  ],
)

点击输出的是 1

_ThroughStack(
  children: [
    Stack(
      children: [
        ...["4","5","6"].map((item)=>GestureDetector(
          onTap: (){
            debugPrint("=====onTap===$item");
          },
          child: Container(
            width: 100,
            height: 100,
            color: Colors.green,
            alignment: Alignment.center,
            child: Text(item,style: const TextStyle(
                fontSize: 16,
                color: Colors.black
            ),),
          ),
        )).toList()
      ],
    ),
    ...["1","2","3"].map((item)=>GestureDetector(
      onTap: (){
        debugPrint("=====onTap===$item");
      },
      child: Container(
        width: 100,
        height: 100,
        color: Colors.green,
        alignment: Alignment.center,
        child: Text(item,style: const TextStyle(
            fontSize: 16,
            color: Colors.black
        ),),
      ),
    )).toList(),
  ],
)

点击输出的是 6