Handle tap event in parent widget - flutter

In my app tree I have two widgets:
GestureDetector(
onTap: () => print('Outer'),
child: IconButton(
icon: Icon(Icons.add),
onPressed: () => print('Inner')),
),
)
Both of them are trying to react to touch event but only child's callback is invoked (which is default behaviour). Is it possible to define widgets in a way that will prevent ancestor from propagating touch event to its children? Or maybe the only way is to implement such behaviour on your own, e.g. by making use of GestureArena?

I think you are looking for the AbsorbPointer widget:
A widget that absorbs pointers during hit testing.
When absorbing is true, this widget prevents its subtree from
receiving pointer events by terminating hit testing at itself. It
still consumes space during layout and paints its child as usual. It
just prevents its children from being the target of located events,
because it returns true from RenderBox.hitTest.
You can use it like this:
GestureDetector(
onTap: () => print('Outer'),
child: AbsorbPointer(
child: IconButton(
icon: Icon(Icons.add),
onPressed: () => print('Inner'),
),
),
),

Related

How to get tap event inside absorb pointer

I have a page containing many widgets which is opened in view only mode. i used AbsorbPointer for ignoring user inputs. but in some cases i have to get onTap event on one button which is inside AbsorbPointer. how can i achieve that ?
I tried using GestureDetector but its not giving onTap event.
any idea??
AbsorbPointer(
absorbing:true,
child: Column(children: [
Text("HELLO"),
Text("HELLO 2"),
GestureDetector(
onTap: () {
showToast("I tried this");
},
child: IconButton(
icon: Icon(
Icons.local_offer,
color: Colors.red,
),
onPressed: () {
print("I need this event");
},
),
)
]),
);
use absorbing: property for your cases... set it to false in the case you want to allow the GestureDetector inside

How can I implement tap-able Text widget, Flutter?

I have a Text widget on pressing which another Route has to be shown. But I could not see any onPressed() method for the Text widget. Please Help.
In your case there are multiple routes where you can go.
Using material TextButton:
TextButton(onPressed: () {}, child: Text('Your child'))
Using InkWell Widget, which covers your widget with 'as button' properties, splashes etc, which allows you to have more customisable buttons taps:
InkWell(onTap: () {}, onDoubleTap: () {}, onLongPress: () {}, onHover: () {}, ..etc , child: Text('Your child widget'))
Using GestureDetector, is the most customisable solution for any gestures you can provide (from its name), can handle taps, long presses, double taps, drags etc.
Syntax is similar:
GestureDetector(onTap: () {}, child: Text('Your child widget'))
Try using TextButton widget:
TextButton(
onPressed: () {},
child: Text('Simple Button'),
),
The best way to make any widget tappable is to use GestrureDetector you just put it outside of the widget/widgets you want and you can use dozen of properties.
For example
GestureDetector(child:
onPressed: () {},
Text('Your text')
)

floatingActionButton shows but figure is empty

Hello This is my code:
floatingActionButton: FloatingActionButton(onPressed:(){
Icon(Icons.edit);
} ,),
The problem is, when i add any icon (like icons.edit or icons.alarm etc.), it shows empty circular button.
floatingActionButton: FloatingActionButton(
onPressed: () {
//do something
},
child: Icon(Icons.edit),
),
This is because you are putting the Icon inside on onPressed. OnPressed is code that executes when the button is pressed, add a child Icon widget.
You haven't added a child to the FloatingActionButton.
Specify the child property of FloatingActionButton
floatingActionButton: FloatingActionButton(
child: Icon(Icons.edit, color: Colors.white),
onPressed:(){
// onPressed function
},
),

How to catch gesture from its child in GestureDetector?

In this part of code only doSthElse() is being called.
GestureDetector(
onTap: doSth,
child: FloatingActionButton(
onPressed: doSthElse,
)
)
If I set null instead of doSthElse, then doSth is called when onTap occurs.
Is there any way to call both methods on the same tap action?
Thanks guys, I figured it out. I merged #Benjamin and #Locked answers and got this:
GestureDetector(
onTap: () {
doSth();
widget.button.onPressed();
},
child: AbsorbPointer(
child: widget.button,
absorbing: true,
),
)
widget is StatefulWidget and code above is in its state build method.

Flutter disable touch on the entire screen

Is there any way to prevent my screen from receiving touch events, I don't want to disable touch for every Widget in my app. I just want to lock the app so that it doesn't receive touch events. How can I do that?
You can wrap your widget in AbsorbPointer and it won't receive touches. To enable the touch again, you can set absorbing: false
AbsorbPointer(
child: YourWidget(...),
);
Two way to do :
AbsorbPointer
IgnorePointer
Check difference with example here :
https://programmer.help/blogs/the-difference-between-flutter-absorbpointer-and-ignorepointer.html
Flutter AbsorbPointer vs IgnorePointer difference
Lets see a practical example of using IgnorePointer widget.
This case is pretty common when we started trying to implement something like toggling a selection on a widget to delete or something like this.
RESULT:
Example Senario :
Holding on a WhatsApp message and delete option coming on top. if tap anywhere else while this option active, it will go.
I implemented it like this.
appBar: AppBar(
title: Text('MyApp'),
actions: [
if (_selected != null) // <-- Delete button only appear something selected.
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
// Delete Code here
}
]
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
print('Tapped');
setState(() { _selected = null });
},
child: IgnorePointer(
ignoring: _selected != null ? true : false, // <-- Ignore only when selecting something.
child: Column(
children: [
...
// This is a sample message
GestureDetector(
onLongPress: () {
setState(() { _selected = messageId });
}
child: Container(
child: Text('This is a message'),
),
...
Hope it will help somebody! Have a nice day.