Flutter- GestureDetector无法与堆栈中的容器一起使用

时间:2018-10-24 09:42:17

标签: flutter gesturedetector

我有两个容器,两个容器都有GestureDetector。第一个容器的OnTap可以正常工作,但不能与另一个容器一起使用。 第一个容器是图像,第二个容器是部分在第一个容器上对齐的绿色背景。

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),
              )
            ],
          )

布局截图

enter image description here

13 个答案:

答案 0 :(得分:2)

尝试将behavior的{​​{1}}属性设置为GestureDetector

答案 1 :(得分:2)

就我而言,我在堆栈中有一个CustomPainter。在我给CustomerPainter设置尺寸之前,以上所有操作均无效。显示时未明确指定大小,但未触发点击事件:

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

答案 2 :(得分:1)

您应该尝试使用 AbsorbPointer 包装您的 Container。

答案 3 :(得分:0)

我认为您的小部件彼此重叠,并且导致了问题。您可以通过用容器包装GestureDetector进行检查,并提供颜色以获得更好的理解。

您的代码还不够,这就是为什么我添加以下示例可以帮助您更清楚地理解。

在示例中交换GestureDetector的位置,您会发现在第一种情况下它仅打印第二个,在其他情况下,如果单击上面的部分,它将首先打印到。

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,
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

答案 4 :(得分:0)

我看到您正在调用回调方法,而不是将其分配给GestureDetector小部件的onTap属性。传递方法名称,不要在此处调用。

答案 5 :(得分:0)

使用InkWell代替GestureDetector解决了我的问题。

答案 6 :(得分:0)

对于其他来此帖子的人,可能导致此问题的另一件事是层次结构更高的AbsorbPointer。

答案 7 :(得分:0)

BuildContext树中的另一个GestureDetector

好的,这对我来说很愚蠢,但是由于它可能发生在我们当中,所以我将解释:

我的构建上下文(为示例简化)树是这样的:

Widget build(BuildContext context) {

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

似乎合法吗?但是后来我检查了树的底部更多细节:

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

快速检查了TheSourceOfEvil,以发现罪魁祸首实际上是另一个OTHER GestureDetector 有一个孩子,我还没有实施onTap: () => {},

Widget TheSourceOfEvil( {

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

摆脱了它,它立即解决了我令人困惑的问题。希望对您有所帮助!

答案 8 :(得分:0)

GestureDetector在其块内编写代码时不起作用 将无法正常工作

GestureDetector(
                  onTap: () {
                    setState(() {
                      _color = Colors.red;
                    });
                  },),

您将这样写,它将起作用

GestureDetector(
                  onTap: () {
                    changed();
                  },),

方法

void changed() {
setState(() {
  _color = Colors.red;
});}

答案 9 :(得分:0)

对我来说,这是一个问题,其中Stack以外的其他项目在clipBehavior: Clip.none之外溢出。

在这种情况下,该项目可见但不可触摸。因此,我更新了布局以删除clipBehavior: Clip.none上的StackGestureDetector开始工作。 ?

答案 10 :(得分:0)

如果您正在使用 GoogleMap 小部件并想要添加搜索字段/文本字段,您应该意识到地图小部件正在消耗您的手势。我做这样的事情:

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(() {});
  }

我正在使用 AbsorbPointer 小部件来吸收点击/点击,但前提是我的文本字段具有焦点。我打电话给我的 rebuildAfterFocusChange();如果我点击我的“搜索字段”,请使用文本字段的 onsubmit 方法在我的后端触发搜索,并在我取消对我的文本字段的关注之后。

答案 11 :(得分:0)

还要考虑 Listener 小部件。它帮助了我。
https://api.flutter.dev/flutter/widgets/Listener-class.html
示例:

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

答案 12 :(得分:-1)

由于stackwidget上有GestureDetector

解决方案:

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