繁体   English   中英

Flutter-GestureDetector 不适用于堆栈中的容器

[英]Flutter- GestureDetector not working with containers in stack

我有两个容器在一个堆栈中,两个容器都有 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),
              )
            ],
          )

布局截图

在此处输入图片说明

尝试将GestureDetectorbehavior属性设置为HitTestBehavior.translucent

使用InkWell而不是GestureDetector解决了我的问题。

对我来说,这是一个项目在Stack外溢出的问题,带有clipBehavior: Clip.none

在这种情况下,该项目可见但不可触摸。 所以我更新了我的布局以删除我的Stack上的clipBehavior: Clip.none并且GestureDetector开始工作。 🎉

就我而言,我在堆栈中有一个 CustomPainter。 在我给 CustomerPainter 一个大小之前,以上都没有奏效。 它在没有明确给出大小的情况下显示,但没有触发点击事件:

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

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

我认为您的小部件彼此重叠并且导致问题。 你可以通过用容器包裹你的 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,
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

由于stack ..您的GestureDetector上有一些widget

解决方案:

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

对于其他人来到这篇文章,另一个可能导致此问题的原因是层次结构更高的 AbsorbPointer。

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 发现罪魁祸首实际上是另一个 GestureDetector有一个孩子,我还没有实现onTap: () => {}, :

Widget TheSourceOfEvil( {

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

摆脱它,它立即解决了我令人费解的问题。 我希望它会有所帮助!

如果您正在使用 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 方法在我的后端触发搜索,并在我取消聚焦我的文本字段之后。

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

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

好的,这是交易,我只是改变了小部件的位置。 在堆栈中,一切都像一个树索引。

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

我的代码:

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

我只是改变了顺序

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM