Search code examples
flutterdartcanvasgesturedetectorpropagation

Propagate click behind a widget


I have a Stack with two widgets inside. I'm trying to detect the click on the bottom widget of the Stack, which is behind the top one.

I am using HitTestBehavior.translucent, but it only work if the GestureDetector doesn't have any child.

This is a simplified version of what i need in my app. I have a Stack which contains many tiny Cards on the screen, and there's one canvas on top of them all. Despite the canvas, I need to be able to tap on the Cards to change its content. I thought using a translucent behavior would solve my problem but it does not.

EDIT : Also, the first GestureDetector will always be in a Positioned widget.

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SizedBox(
          height: 800,
          width: 400,
          child: Stack(
            children: [
              /// 2. ... and trigger the onTap function of this widget
              GestureDetector(
                behavior: HitTestBehavior.opaque,
                onTap: () {
                  print('TAP BOTTOM');
                },
                child: Container(
                  height: 500,
                  width: 400,
                  color: Colors.deepOrange,
                ),
              ),
              /// 1. I'm Trying to clic here...
              GestureDetector(
                behavior: HitTestBehavior.translucent,
                onTap: null,
                child: Container(
                  height: 300,
                  width: 400,
                  color: Colors.deepPurple,
                ),
              ),
            ],
          ),
        ),
        // ),
      ),
    );
  }
}

Solution

  • Wrap the widget(s) you want the click to propagate through in IgnorePointer:

    IgnorePointer(
      ignoring: true,
      child: widgetThatIgnoresClicks()
    )
    

    Full sample code with which you can achieve this:

    ​class TestPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: SizedBox(
              height: 800,
              width: 400,
              child: Stack(
                children: [
                  /// 2. ... and trigger the onTap function of this widget (WIDGET_2)
                  GestureDetector(
                    behavior: HitTestBehavior.opaque,
                    onTap: () {
                      print('TAP BOTTOM');
                    },
                    child: Container(
                      height: 500,
                      width: 400,
                      color: Colors.deepOrange,
                    ),
                  ),
                  /// Able to tap bottom
                  IgnorePointer(
                    ignoring: true,
                    child: Container(
                      height: 300,
                      width: 400,
                      color: Colors.deepPurple,
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    

    Also sorry for posting late here.