96

I want to have a blurred image on top of my other widgets, however, I cannot interact with the widgets below it when I do that.

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Mohamed Mohamed
  • 3,965
  • 3
  • 23
  • 40
  • Possible duplicate of [How do I do the "frosted glass" effect in Flutter?](https://stackoverflow.com/questions/43550853/how-do-i-do-the-frosted-glass-effect-in-flutter) – creativecreatorormaybenot May 30 '18 at 11:40
  • Not really @creativecreatorormaybenot , I want to have the previous page seen blurred not sit a random image and the content which a box seen clearly as if hovering over it with a drop shadow. – Mohamed Mohamed May 30 '18 at 13:38
  • Yes I got that. But because Flutter works exclusively with `Widget`'s the answer of that question is applicable to your question as well. Your whole page can simply be wrapped with a `BackdropFilter`. – creativecreatorormaybenot May 30 '18 at 14:25
  • I’ve tried that. The black still shows. I don’t know where that black is coming from. well I kinda do, only happens after the navigate to function. Unless there’s another way to fade in a widget, pass data, and then return it as well if any data has changed ? – Mohamed Mohamed May 30 '18 at 17:31

3 Answers3

196

Solution

You can solve your interaction issue (not being able to interact with the Widget below your blurred image) by surrounding your BackdropFilter with an IgnorePointer.

This means that IgnorePointer is the solution here because it will ignore all touch events for the Widget's passed as its child.

IgnorePointer(child: BackdropFilter(...),)

You can adjust this attribute by changing the bool value of ignoring:

IgnorePointer(ignoring: false, ...)

This will enable all touch events again.

Absorbing

Something interesting to look at here, but unrelated to the problem, is the AbsorbPointer Widget, which can be used to reflect all touch events that occur on its child onto itself.

PrzemekTom
  • 1,328
  • 1
  • 13
  • 34
creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
74

You can either use IgnorePointer or AbsorbPointer.

  • IgnorePointer

    IgnorePointer(
      child: ElevatedButton(
        onPressed: () {},
        child: Text('Not clickable Button'),
      ),
    );
    
  • AbsorbPointer

    AbsorbPointer(
      child: ElevatedButton(
        onPressed: () {},
        child: Text('Not clickable Button'),
      ),
    );
    

What's the difference?

If there is a widget beneath your main widget which is also capable of receiving click events, and you use IgnorePointer on the parent widget, the child widget would still receive the click events.

But using AbsorbPointer on main widget won't allow the other widget (beneath main widget) to receive their click events.

Example showing the difference.

@override
Widget build(BuildContext context) {
  return SizedBox(
    width: double.infinity,
    child: Stack(
      children: <Widget>[
        Positioned(
          left: 0,
          width: 250,
          child: ElevatedButton(
            color: Colors.red,
            onPressed: () => print("Button 1"),
            child: Text("Button 1"),
          ),
        ),
        Positioned(
          right: 0,
          width: 250,
          child: IgnorePointer( // replace this with AbsorbPointer and button 1 won't receive click
            child: ElevatedButton(
              onPressed: () => print("Button 2"),
              child: Text("Button 2"),
            ),
          ),
        ),
      ],
    ),
  );
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
0

UPDATED

The other answers are very appealing.

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 for example.

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'),
              ),
               
              ...

RESULT:

Hope it will help somebody! Have a nice day.

MBK
  • 2,589
  • 21
  • 25