簡體   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