Repository navigation
Add more explanations of HitTestBehavior #18450
Description
Internal: b/155674981
When I use GestureDetector and put behavior = translucent, I cannot tap on anything bellow it. Also when I use GestureDetector and put behavior lets say opaque and have RawMaterialButton as a child, taps on button are registered on Button but not on GestureDetector and expected behavior in this case would be that taps do not pass to the child.
Example:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Stack(
children: <Widget>[
new Positioned(
left: 0.0,
right: 0.0,
top: 200.0,
bottom: 200.0,
child: new TextField(
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.blue,
),
),
),
new Positioned.fill(
child: new GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: (){
print("Clicked gesture");
},
),
),
// new Positioned.fill(
// child: new GestureDetector(
// behavior: HitTestBehavior.opaque,
// onTap: (){
// print("Clicked gesture");
// },
// child: new RawMaterialButton(
// child: new Text(
// 'BUTTON',
// textAlign: TextAlign.center,
// ),
// onPressed: (){
// print("Clicked button");
// },
// ),
// ),
// ),
],
),
);
}
}In this example, I would expect that GestureDetector receives tap input, but also that TextField gets focus, but what happens is that taps are registered in GestureDetector, but nothing passes to the TextField. If I comment out GestureDetector part, TextField works.
Further, you can comment out first two widgets in stack and uncomment last one to check other issue- when GestureDetector has child. I would expect that no tap is passed to child but child receives input and GestureDetector does not.
flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel master, v0.5.5-pre.10, on Mac OS X 10.13.4 17E202, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
[✓] iOS toolchain - develop for iOS devices (Xcode 9.4)
[✓] Android Studio (version 3.1)
[!] IntelliJ IDEA Ultimate Edition (version 2018.1.2)
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] Connected devices (2 available)
Activity
zoechi commentedon Jun 14, 2018
@Hixie
[-]GestureRecognizer doesn't handle HitTestBehavior correctly[/-][+]GestureDetector doesn't handle HitTestBehavior correctly[/+]Hixie commentedon Jun 14, 2018
opaquejust means the entire size of the gesture detector is the hit region, it doesn't stop the child from being hit. To block hits on children use anIgnorePointerorAbsorbPointer.translucentmeans that the hit testing will traverse below. However, if both widgets are listening for the same gesture, in this case Tap, only one will "win". You can tell that both are getting the pointers though by listening toonTapDowninstead ofonTap.fralways commentedon Jun 14, 2018
Oh my, I completely misunderstood this. I guess adding those comments to the HitTestBehavior enum description would prevent other people from misunderstanding as well. I'm wondering now how can we register same event on multiple widgets?
Hixie commentedon Jun 14, 2018
Use a PointerListener instead of a GestureDetector.
[-]GestureDetector doesn't handle HitTestBehavior correctly[/-][+]Add more explanations of HitTestBehavior[/+]zoechi commentedon Jun 15, 2018
@Hixie do you mean https://docs.flutter.io/flutter/rendering/RenderPointerListener-class.html?
Flutter.io doesn't find anything with
PointerListenerHixie commentedon Jun 18, 2018
Sorry it's just called
Listenerat the widget level. (It's the one that creates a RenderPointerListener.)kaustavjaiswal commentedon Aug 4, 2018
@Hixie I am facing the same issue, I have a Stack widget on the main app screen and the last widget on the stack intercepts all the onTap calls, any example on how to make the onTap reach the lower widgets, positioned lower in the stack would be extremely helpful.
grigy commentedon Aug 30, 2018
I have a similar issue. I want to wrap the child of a Dismissible widget with a GuestureDetector so that I can catch the horizontal swipe events and add additional functionality. But when I use GestureDetector the Dismissible stops to respond to swipe actions.
wwwdata commentedon Oct 9, 2018
@kaustavjaiswal did you find a solution for this problem? Also have this issue.. The only solution for me is to put things that need gestures on top, so at the end of the stack list.
kaustavjaiswal commentedon Oct 9, 2018
@wwwdata I am doing the same thing today.
https://flutter.io/gestures/
The gesture disambiguation section here helps to understand how flutter is treating these gestures.
26 remaining items
alexeyselina commentedon Nov 12, 2020
Does somebody know how to fix StackWithAllChildrenReceiveEvents class?
I'm totally confused with overriding of
'bool hitTestChildren(BoxHitTestResult result, { required Offset position }) '
When I'm trying to overload it offers me this method:
@override bool hitTestChildren(BoxHitTestResult result, {Offset}) { // TODO: implement hitTestChildren return super.hitTestChildren(result, Offset); }I have 2.10.3 Dart version but the syntax causes compilation issues.
xJon commentedon Nov 12, 2020
@alexeyselina This is how I have it:
h65wang commentedon Dec 30, 2020
FWIW, this example correctly showcases all 3 HitTestBehaviors, remember to long press when testing:
allComputableThings commentedon Dec 30, 2020
Yes... works for Stacks, but not for nested widgets, which I would think is the very common cases.
allComputableThings commentedon Jan 6, 2021
A simple workaround to the bug of duplicate events when mixing GeatureRecognizer and Listener in parent child relationships is to wrap the Listener with an additional
Thanks to: https://stackoverflow.com/questions/65572920/how-to-avoid-duplicate-events-when-combining-gesturedetector-and-listener-in-flu
giorgio79 commentedon Feb 1, 2021
Testing StackWithAllChildrenReceiveEvents
I notice overflow is getting an error, saying the setter is not defined using flutter stable channel
giorgio79 commentedon Feb 1, 2021
I completed testing StackWithAllChildrenReceiveEvents for the issue with sample at #75086 (comment)
The bottom child in the Stack is now receiving the events, so all looks good! Thanks a lot!! :)
I had to remove the EagerGestureRecognizer from the bottom child, GoogleMap, since with that none of the children above the GoogleMap were getting gestures. Without EagerGestureRecognizer it works like magic.
Hixie commentedon Feb 3, 2021
Closing in preference to #74733 which has a start to text and diagrams we could add.
github-actions commentedon Aug 6, 2021
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.