[英]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),
)
],
)
布局截圖
嘗試將GestureDetector
的behavior
屬性設置為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×tamp=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。
好吧,在我看來,這很愚蠢,但由於我們許多人可能會發生這種情況,我將解釋:
我的構建上下文(為示例簡化)樹是這樣的:
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.