How can I remove the overlayEntry when I click outside in Flutter?

Viewed 3149

I want to have a function like popupwindow in Android .

And I have tried for this .

class CommunityMenu {
  static OverlayEntry overlayEntry;

  static void showMenu(BuildContext context) {
    if (overlayEntry == null) {
      overlayEntry = new OverlayEntry(builder: (context) {
        return Positioned(
          right: 12,
          top: 60,
          child: Container(
            color: Colors.white,
            width: 132,
            height: 153,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: <Widget>[
                GestureDetector(
                  onTap: (){
                    overlayEntry.remove();
                  },
                  child: Row(
                    children: <Widget>[
                      Text(
                        "Text1",
                        style: TextStyle(
                            color: Color(0xff4d4d4d), fontSize: 14),
                      )
                    ],
                  ),
                ),
                GestureDetector(
                  onTap: () {overlayEntry.remove();
                  },
                  child: Row(
                    children: <Widget>[
                      GestureDetector(
                        onTap: (){
                          overlayEntry.remove();
                        },
                        child: Text(
                          "Text2",
                          style: TextStyle(
                              color: Color(0xff4d4d4d), fontSize: 14),
                        )
                      )
                    ],
                  ),
                ),
                GestureDetector(
                  onTap: (){
                    overlayEntry.remove();
                  },
                  child: Row(
                    children: <Widget>[
                      Text(
                        "Text3",
                        style: TextStyle(
                            color: Color(0xff4d4d4d), fontSize: 14),
                      )
                    ],
                  ),
                )
              ],
            ),
          ),
        );
      });
    }

    Overlay.of(context).insert(overlayEntry);
  }

  static void dismissMenu() {
    if (overlayEntry != null) {
      overlayEntry.remove();
      overlayEntry = null;
    }
  }
}

You can see that when I click the menu item , I can dismiss the menu ( overlayEntry.remove();) . The problem is now I want to dismiss the menu when I click outside not inside the menu . It Looks like dismiss the keyboard when click outside .

2 Answers

You could make the overlay into a stack and make the bottom layer take up the full screen, wrap it's child in a GestureDetector that calls overlayEntry.remove(). The code below shows what I mean. Also, your onTap calls within the popup are simply calling .remove() but that means the overlayentry is still built. You already have a dismiss() function that you could call instead (which is what I did).

return Stack(
  children: <Widget>[
    Positioned.fill(
        child: GestureDetector(
          onTap:dismissMenu,
          child: Container(
            color: Colors.transparent,
          ),
        )
    ),
    Positioned(
      right: 12,
      top: 60,
      child: //column code here
    ),
  ],
);

It looks like you are trying to build a standard alert dialog. If so, you should take a look at "showDialog" method, instead of trying to build it using Overlay.

For example, this is a button that brings up a pop up dialog, and you can dismiss the dialog by tapping anywhere outside of it, or clicking the back button. Code:

ElevatedButton(
  child: Text("show dialog"),
  onPressed: () {
    showDialog(
      context: context,
      // barrierColor: Colors.transparent,
      builder: (_) => Center(
        child: Container(
          width: 200,
          height: 200,
          color: Colors.white,
        ),
      ),
    );
  },
)

If you don't want the grey color outside of the dialog, or want to change its color, you can use the barrierColor parameter as I commented out in the code above.

Related