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

Issue

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.

Answered By – Norbert

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published