Flutter- GestureDetector not working with containers in stack

FlutterGesturedetector

Flutter Problem Overview


I have two containers in a stack and both containers have GestureDetector.The OnTap for the first container is working fine but it's not working with another container. The first container is the image and the second one is the green background aligned partially over the first container.

new Stack(
            alignment: Alignment(0.0, 1.44),
            children: <Widget>[
              GestureDetector(
                onTap: () => _openImage(context),
                child: Container(
                  width: 340.0,
                  foregroundDecoration: new BoxDecoration(
                      color: Color.fromRGBO(155, 85, 250, 0.55)),
                  height: 240.0,
                  child: FadeInImage.assetNetwork(
                    placeholder: 'assets/dimlight.png',
                    image: post.imageUrl,
                    fit: BoxFit.cover,
                  ),
                ),
              ),
              new GestureDetector(
                child: new Container(
                  color: Colors.green,
                  child: Row(
                    mainAxisSize: MainAxisSize.max,
                    children: <Widget>[
                      SizedBox(width: 7.0),
                      CircleAvatar(
                        backgroundImage: 
                           new AssetImage("assets/boy.png")
                        radius: 30.0,
                      ),
                      SizedBox(
                        width: 7.0,
                      ),
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          new SizedBox(
                            height: 20.0,
                          ),
                          Text(
                            post.user.name,
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                          Text(
                            getTimeString(post.timestamp.toString()),
                            style: TextStyle(
                                color: Colors.grey, fontSize: 10.0),
                          ),
                        ],
                      ),
                      SizedBox(
                        width: 20.0,
                      ),
                    ],
                  ),
                ),
                onTap: () => _navigateToDetails(context),
              )
            ],
          )

Layout Screenshot

enter image description here

Flutter Solutions


Solution 1 - Flutter

Try setting the behavior property of GestureDetector to HitTestBehavior.translucent.

Solution 2 - Flutter

Using InkWell instead of GestureDetector solved my problem.

Solution 3 - Flutter

You should try wrap your Container with an AbsorbPointer.

GestureDetector(
   child: AbsorbPointer(
      child: Container(...)
   )
)

Solution 4 - Flutter

For me it was an issue with items overflowing outside a Stack, with clipBehavior: Clip.none.

In that case the item is visible but not touchable. So I updated my layout to remove the clipBehavior: Clip.none on my Stack and the GestureDetector started working. 

Solution 5 - Flutter

In my case I had a CustomPainter inside the stack. Nothing of the above was working, until I gave the CustomerPainter a size. It was showing without explicitly giving a size, but no tap events were triggered:

Container(
      child: CustomPaint(
    size: Size(30, 30),
    painter: RecordingButton(30),
  ))

Solution 6 - Flutter

Also consider Listener widget. It helped me.
https://api.flutter.dev/flutter/widgets/Listener-class.html
Example:

Listener(
	onPointerDown: (_) {}, // onTapDown
	onPointerUp: (_) => {}, // onTapUp
	child: Container(),
)

Solution 7 - Flutter

i think that your widgets are overlapping each other and that the causing a problem. you can check it by wrapping your GestureDetector with container and provide color to get better understanding.

your code is not enough that's why i added following example may help you to understand more clearly.

swap the position of GestureDetector in example and you can found that in first case it prints only second and in other case if you click in above part then it prints first to.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Firebase Auth Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Card(
        margin: EdgeInsets.all(40.0),
        child: new Column(
          mainAxisSize: MainAxisSize.max,
          children: <Widget>[
            GestureDetector(
              onTap: () => print("first container"),
              child: Container(
                width: 340.0,
                foregroundDecoration: new BoxDecoration(
                    color: Color.fromRGBO(155, 85, 250, 0.0)),
                height: 240.0,
                child: FadeInImage.assetNetwork(
                  placeholder: 'images/p1.png',
                  image:
                  "https://www.straitstimes.com/sites/default/files/styles/article_pictrure_780x520_/public/articles/2016/06/15/ST_20160615_LLIMH_2368135.jpg?itok=8Dggu2PM&timestamp=1465926004",
                  fit: BoxFit.cover,
                ),
              ),
            ),
            new GestureDetector(
              child: new Container(
                foregroundDecoration: BoxDecoration(
                    color: Color.fromRGBO(155, 85, 250, 0.4)),
                child: Row(
                  mainAxisSize: MainAxisSize.max,
                  children: <Widget>[
                    SizedBox(width: 7.0),
                    CircleAvatar(
                      backgroundImage: new AssetImage("images/p2.jpg"),
                      radius: 30.0,
                    ),
                    SizedBox(
                      width: 7.0,
                    ),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          new SizedBox(
                            height: 20.0,
                          ),
                          Text(
                            "sfvgefbv",
                            style: TextStyle(fontWeight: FontWeight.bold),
                          ),
                          Text(
                            "sfvmsfkv",
                            style: TextStyle(
                                color: Colors.grey, fontSize: 10.0),
                          ),
                        ],
                      ),
                    ),
                    new Container(
                      alignment: AlignmentDirectional.centerEnd,
//            todo add here check if not logged in then ask to
                      child: Row(
                        mainAxisSize: MainAxisSize.min,
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: <Widget>[
                          IconButton(
                              icon: Icon(
                                Icons.comment,
                                color: Colors.green,
                              ),
                              onPressed: () => print("message click")),
                          Text(
                            "2",
                            style: TextStyle(
                              color: Colors.green,
                            ),
                          ),
                          SizedBox(
                            width: 10.0,
                          )
                        ],
                      ),
                    ),
                  ],
                ),
              ),
              onTap: () => print("this is second container"),
            ),
            new Expanded(
              child: Container(
                padding: EdgeInsets.all(10.0),
                child: Column(
                  children: <Widget>[
                    Text(
                      "fsvkmfskbnmkffvberk",
                      style: TextStyle(
                          color: Colors.green, fontWeight: FontWeight.bold),
                    ),
                    new Text(
                      "svklmfslkbnernkjrnvkrwjnvrw",
                      maxLines: 6,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Solution 8 - Flutter

Another GestureDetector in the BuildContext tree

Ok on my side it was quite stupid but since it may happens to many of us I will explain:

My build context (simplified for the example) tree was this way:

Widget build(BuildContext context) {

return (...) (
    child: GestureDetector(
        onTap: () => _myFunction(),
        child: Container(
            height: 64.0,
            width: 128.0,
            child: (...)

Seems legit right? But then I inspected into more details the bottom of my tree:

(...)
        onTap: () => _myFunction(),
        child: Container(
            height: 64.0,
            width: 128.0,
            child: TheSourceOfEvil() // <-- whoopsie!

Quickly inspected TheSourceOfEvil to find out that the culprit was in fact ANOTHER GestureDetector has a child, that I had not yet implemented onTap: () => {},:

Widget TheSourceOfEvil( {

return (...) (
    child: GestureDetector(
        onTap: () => {}, // override previous GestureDetector
        child: Container(
            child: (...);

Got rid of it and it instantly fixed my puzzling issue. I hope it will help!

Solution 9 - Flutter

Because of stack..There are some widget on your GestureDetector.

Solution:

Stack(
        children: <Widget>[
              ...//Other widgets,
              GestureDetector()
        ]

Solution 10 - Flutter

For others coming to this post, another thing that can cause this issue is an AbsorbPointer higher is the hierarchy.

Solution 11 - Flutter

If your are using GoogleMap widget and want to add a searchfield/textfield you should be aware that the map widget is consuming your gestures. I do something like this:

final FocusNode _focusNode = new FocusNode();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.translucent,
      onTap: () {            
        print("tap");
        if (_focusNode.hasPrimaryFocus) {
          _focusNode.unfocus();
          rebuildAfterFocusChange();
        }
      },
      child: Stack(children: [
        AbsorbPointer(absorbing: _focusNode.hasPrimaryFocus, child: StoreMapView()),
        showSearchField(model),
      ]),
    );
  }

Widget showSearchField(StoreFinderViewModel model) {
    return SafeArea(
      child: Padding(
        padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 12.0),
        child: TextField(
          onTap: () {
            rebuildAfterFocusChange();
          },
          onSubmitted: (String input) {
            rebuildAfterFocusChange();
            // do other stuff
            });
          },
          focusNode: _focusNode,
        ),
      ),
    );
  }

  void rebuildAfterFocusChange() {
    setState(() {});
  }

I am using the AbsorbPointer widget to absorb the clicks/taps, but ONLY if my textfield has the focus. I call my rebuildAfterFocusChange(); if I tap on my "Searchfield", use the onsubmit method of the textfield to trigger a search in my backend and after I unfocus my textfield.

Solution 12 - Flutter

Okay here's the deal, I just changed the position of the widgets. In Stack Everything is like a Tree index.

Stack Parent
  └ Child One    [Far Back]
  └ Child Two
  └ Child Three  [Top Front]

My Code:

     return Stack(
              children: [
                accountInfo(),   // this is not clickable
                chatMessages(),
                typingArea(),
              ],
            ),

I just changes the sequence

    return Stack(
              children: [
                chatMessages(),
                typingArea(),
                accountInfo(), // Now this is clickable by any of onTap Event ad
              ],
            ),

Solution 13 - Flutter

For my case, I placed the GestureDetector inside the Stack which created the same problem. I solved it by making the parent Stack into a child of the GestureDetector .

Before -

Stack(
    children: [
    GestureDetector()
    ])

After -

GestureDetector(
    child: 
    Stack()
   )

Solution 14 - Flutter

To handle ontap events in Stack widgets you can use transparent_pointer

Example :

 class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        GestureDetector(
          behavior: HitTestBehavior.opaque,
          onVerticalDragStart: (_) => print("Background drag started"),
        ),
        Positioned(
          top: 60,
          left: 60,
          height: 60,
          width: 60,
          child: TransparentPointer(
            child: TextButton(
              child: Text("Tap me"),
              onPressed: () => print("You tapped me"),
            ),
          ),
        ),
      ],
    );
  }
}

Solution 15 - Flutter

I see that you are calling the callback method instead of assigning it to onTap property of GestureDetector widget. Pass the name of the method don't call it there.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHimanshu YadavView Question on Stackoverflow
Solution 1 - FlutterAthul SaiView Answer on Stackoverflow
Solution 2 - FlutterSobhan MoradiView Answer on Stackoverflow
Solution 3 - FlutterMichel FortesView Answer on Stackoverflow
Solution 4 - FlutterHugo HView Answer on Stackoverflow
Solution 5 - FlutterstanView Answer on Stackoverflow
Solution 6 - FlutterRodion MostovoyView Answer on Stackoverflow
Solution 7 - FlutterViren V VarasadiyaView Answer on Stackoverflow
Solution 8 - FlutterAntonin GAVRELView Answer on Stackoverflow
Solution 9 - FlutterBIS TechView Answer on Stackoverflow
Solution 10 - Flutterjohngray1965View Answer on Stackoverflow
Solution 11 - Flutterbasti12354View Answer on Stackoverflow
Solution 12 - FlutterSayed Muhammad IdreesView Answer on Stackoverflow
Solution 13 - FlutterGk Mohammad EmonView Answer on Stackoverflow
Solution 14 - FlutterMANISHView Answer on Stackoverflow
Solution 15 - FlutterpaulosView Answer on Stackoverflow