Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a GestureDetector capture taps inside a Stack?

Tags:

flutter

I'm trying to make a GestureDetector work inside a Stack with a Container on top of it but the onTap callback is never called.

As you can see, it doesn't work even with HitTestBehavior.translucent

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: <Widget>[
            GestureDetector(
              behavior: HitTestBehavior.translucent,
              onTap: () {
                print('tap');
              },
              child: Container(color: Colors.blue),
            ),
            Container(color: Colors.white),
          ],
        ),
      ),
    );
  }

I know that it can be strange that I would want to capture tap event below another Widget but in my real case, the widget on top is transparent and sometimes has a gradient.

like image 808
Vardiak Avatar asked Aug 12 '19 18:08

Vardiak


People also ask

What is the difference between InkWell and GestureDetector?

They both look the same and almost do the same thing, so what is difference between flutter InkWell vs GestureDetector? Generally speaking, GestureDetector provides more gesture control to detect almost every user interaction including dragging, swiping, pinching, etc.

How do you know if your tap is fluttering?

Use GestureDetector's behavior property and pass HitTestBehavior. opaque to it, which recognizes entire screen and detects the tap when you tap anywhere on the screen.

Is ONTAP of gesturedetector working for containers in stack?

OnTap of GestureDetector is not working for containers in stack. · Issue #23454 · flutter/flutter · GitHub Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community. By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement.

How to use gesturedetector() in scaffold()?

In the body of Scaffold (), we pass Center () and after that, we pass GestureDetector () as a child of it. We create a Container () and pass the color and text which is already passed the code.

Why does my gesturedetector have no color?

Just make sure that your gesturedetector is not overlapped with other widgets that has color. stack [ gesturedetector, container, widgets... ] make sure that the container has no color because even transparent color can overlap the inputs.

What is gesturedetector in flutter?

GestureDetector In Flutter. When it comes to creating applications… | by Raksha Goswami | FlutterDevs W hen it comes to creating applications, you have to handle user reactions such as touch and drags. This makes your application interactional beneficially handle gestures, you need to listen to the gestures and greet them.


1 Answers

Ok guys, I think I found a solution myself. I hope that there exist a simpler solution but it works for my use. The problem I had was that the Stack widget doesn't pass the hit test to all children but only the first one that is hit. What I did is that I rewrote the hit detection algorithm used by the Stack's RenderBox. I really didn't intended to go this far and I'm still waiting for a better answer. Here is my code, use it at your own risk :

class CustomStack extends Stack {
  CustomStack({children}) : super(children: children);

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

class CustomRenderStack extends RenderStack {
  CustomRenderStack({alignment, textDirection, fit, overflow})
      : super(
            alignment: alignment,
            textDirection: textDirection,
            fit: fit,
            overflow: overflow);

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

    final children = getChildrenAsList();

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

      final 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;
  }
}

like image 119
Vardiak Avatar answered Oct 11 '22 09:10

Vardiak