Search code examples
fluttergestureflutter-layout

In Flutter, how can a positioned Widget feel taps outside of its parent Stack area?


A Stack contains MyWidget inside of a Positioned.

Stack(
  overflow: Overflow.visible,
  children: [
    Positioned(
    top: 0.0,
    left: 0.0,
    child: MyWidget(),
  )],
);

Since overflow is Overflow.visible and MyWidget is larger than the Stack, it displays outside of the Stack, which is what I want.

However, I can't tap in the area of MyWidget which is outside of the Stack area. It simply ignores the tap there.

How can I make sure MyWidget accepts gestures there?


Solution

  • This behavior occurs because the stack checks whether the pointer is inside its bounds before checking whether a child got hit:

    Class: RenderBox (which RenderStack extends)

    bool hitTest(BoxHitTestResult result, { @required Offset position }) {
    
        ...
    
        if (_size.contains(position)) {
          if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
            result.add(BoxHitTestEntry(this, position));
            return true;
          }
        }
        return false;
    }
    

    My workaround is deleting the

    if (_size.contains(position))
    

    check. Unfortunately, this is not possible without copying code from the framework.

    Here is what I did:

    • Copied the Stack class and named it Stack2
    • Copied RenderStack and named it RenderStack2
    • Made Stack2 reference RenderStack2
    • Added the hitTest method from above without the _size.contains check
    • Copied Positioned and named it Positioned2 and made it reference Stack2 as its generic parameter
    • Used Stack2 and Positioned2 in my code

    This solution is by no means optimal, but it achieves the desired behavior.