
Flutter Widget In Detail : AbsorbPointer & IgnorePointer
Detailed Explanation of AbsorbPointer & IgnorePointer Widgets
Introduction :
- Have you ever been in a situation in your app where there are multiple buttons, listview, list tiles, cards, containers, etc, and you want to stop interaction/touches from the user from all of those widgets at once?
- Of course, you can pass
nullto the buttonsonPressedproperty. But when there are too many buttons in your row/column or any other widget, it is very frustrating to pass this property one by one. - Consider the below example where there are 5 buttons inside
Column. Now we want to disable all the buttons for some reason. For that, the common way is to go and writenullto every button'sonPressedproperty.Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton(child:Text("1"),onPressed:null), SizedBox(height:5.0), ElevatedButton(child:Text("2"),onPressed:null), SizedBox(height:5.0), ElevatedButton(child:Text("3"),onPressed:null), SizedBox(height:5.0), ElevatedButton(child:Text("4"),onPressed:null), SizedBox(height:5.0), ElevatedButton(child:Text("5"),onPressed:null), ] ) - Isn't it a very boring way to do this? Yes IT IS. And what if we want to disable all the interactions from our app at once ๐ง?

- So what's the solution to this problem? ๐ค
- Well Flutter provided two very useful widgets to solve this problem. The solution is to wrap your widget inside AbsorbPointer / IgnorePointer.

- You can disable the user's whole app interaction by simply wrapping your main widget from the widget tree inside the AbsorbPointer.
- Let's see both the widget one by one and understand what they are doing and what is the difference between them.
AbsorbPointer :
- As the name screaming, AbsorbPointer absorbs the click event. In other words, It prevents click events from the child widget.
- Not only it prevents
clickevents, but it also preventsscroll,drag,hoverevents. Properties :
absorbing: Whentrue, The widget prevents its subtree from receiving all kinds of events. Whenfalse, The widget will allow its subtree to receive the events.child: Pass widget/widgets from which you want to disable events.ignoringSemantics: This takes boolean as a parameter.truemeans widget should be ignored by screen readers when compiling the semantic tree.- Example :
Stack( alignment: AlignmentDirectional.center, children: <Widget>[ SizedBox( width: 200.0, height: 100.0, child: ElevatedButton( onPressed: () {}, child: null, ), ), SizedBox( width: 100.0, height: 200.0, child: AbsorbPointer( absorbing: true, child: ElevatedButton( style: ElevatedButton.styleFrom( primary: Colors.red.shade200, ), onPressed: () {}, child: null, ), ), ), ], ); - Output :

- Here we can clearly see that the red Box is completely disabled. If you observe the
onPressedproperty of the red button, it is not null, but still, it is not receiving any kind of event because we've wrapped our button inside the AbsorbPointer - This is a very small example. But imagine if have too many widgets on your screen like below,

- Then AbsorbPointer is the right and best way to disable everything at once.
IgnorePointer :
- As the name screaming, IgnorePointer ignores/prevents their children's widget from pointer-events as well as the whole widget tree interaction.
- Like AbsorbPointer, IgnorePointer can ignore pointer-events like tapping, dragging, scrolling, and hover.
Properties :
ignoring: Iftrueit will ignore the pointer event.child: Pass widget/widgets from which you want to disable events.ignoringSemantics: Iftruethe widget will be ignored when compiling the semantics tree. And will be ignored by the screen readers- Example :
Center( child: IgnorePointer( ignoring: ignoring, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Text('Ignoring: $ignoring'), ElevatedButton( onPressed: () {}, child: const Text('Click me!'), ), ], ), ), ), - Output :

- As you can see that when we change the value of the
ignoringfromfalsetotrue, the button is no longer clickable.
- Hh ๐ค !! So what's the difference between AbsorbPointer and IgnorePointer? Both are doing the same thing right !! But NO there are some differences. Let's see.
- So let's understand the core difference between both of them by taking an example.
Difference Between AbsorbPointer and IgnorePointer :
Example - 1 :
- Consider two boxes
redbox and thebluebox. The red box is on top of the blue box.
Stack(
alignment: Alignment.topCenter,
children: [
BlueBox(
onClicked: () {print("Blue box clicked")}.
child: Container(width: 200, height: 150),
color: Colors.blue,
),
RedBox(
onClicked: () {print("Red box clicked")}.
child: Container(width: 100, height: 100),
color: Colors.red,
),
]
)
- All is working as aspected. Both buttons are working with their individual
onClickedproperty.

- Now we are going to wrap the
redbox inside theIgnorePointer. Let's see what happens IgnorePointer( child: RaisedButton( onPressed: (){print("Red box clicked")}, child:Container( child: Container(width: 100, height: 100), color: Colors.red, ), ) )Output :

As we can observe that now the
redbox is not clickable anymore. Even if we click on theredbox thebluebox will be clicked.Now let's wrap the same
redbox with the AbsorbPointer and see what happens.AbsorbPointer( child: RaisedButton( onPressed: (){print("Red box clicked")}, child:Container( child: Container(width: 100, height: 100), color: Colors.red, ), ) )
Now you can see that the
redbox is not even showing that click event/hand cursor.- So basically AbsorbPointer is ignoring the interaction of the child widget by also ignoring the widget below it, which here is some part of the
bluebox below theredbox. IgnorePointer is also ignoring the interaction of the child widget. But it will not ignore the widget below it.
Simply put, In AbsorbPointer what is happening is that The
redbox contains some part of thebluebox below it, that's why it is also absorbing/ignoring that part and disable it.But IgnorePointer will not absorb/ignore that below part and it will make the whole box clickable by not considering the
redbox click event
Example - 2 :
- Consider a Button. which is also wrapped inside
GestureDetectorwidget.GestureDetector( onTap: (){ print("Gesture Detector"); }, child:ElevatedButton( style: ElevatedButton.styleFrom(primary: Colors.transparent), onPressed: (){ print("Red Button Pressed"); }, child:Container(width: 100, height: 100,color:Colors.red), ) ) 
- When you click on this box, it will print
Red Button Pressedas expected. Notice that it will not call theonTapfunction of theGestureDetectorwidget. - Now let's wrap the
ElevatedButtoninside ourIgnorePointer.GestureDetector( onTap: (){ print("Gesture Detector"); }, child: IgnorePointer( child: ElevatedButton( style: ElevatedButton.styleFrom(primary: Colors.transparent), onPressed: (){ print("Red Button Pressed"); }, child:Container(width: 100, height: 100,color:Colors.red), ) ) ) - Now what do you think .... what will happen if we click on the red box again ๐ค??
- Will it print the statement of
GestureDetectororElevatedButton?? - It will not print any of the statements!!!. Why ?? Because as we've discussed above that
IgnorePointerwill ignore its child as well as its whole widget tree.. It means it will also ignore theGestureDetectorbecause it is also a part of theIgnorePointers widget tree. 
Now let's wrap our button inside AbsrobPointer.
GestureDetector( onTap: (){ print("Gesture Detector"); }, child: AbsorbPointer( child: ElevatedButton( style: ElevatedButton.styleFrom(primary: Colors.transparent), onPressed: (){ print("Red Button Pressed"); }, child:Container(width: 100, height: 100,color:Colors.red), ) ) )
- As we can see the event of our
ElevatedButtonis ignored but theonTapof theGestureDetectoris working. Because theAbsorbPointerwill only absorb the child of it. Not the whole widget tree.
That's IT. That's all you need to about AbsorbPointer and IgnorePointer. Hope you understood. ๐
Previous Blog : Widget In Detail - Container
