Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to close an overlay by clicking on outside in flutter

Tags:

flutter

dart

I'm creating an overlay onClick of a button, that is working fine from below code, but I want to close the overlay by clicking outside of it.

enter image description here

Reference code:

  • For creating overlay I'm using OverlayEntry

  • Setting the overlay position by using offset which is available when taped on any of the six buttons.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: GesturePositionDetector(),
    );
  }
}

class GesturePositionDetector extends StatelessWidget {
  OverlayState overlayState;
  OverlayEntry _overlayEntry;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              _getButtons([1, 2, 3], context),
              _getButtons([4, 5, 6], context),
              _getButtons([7, 8, 9], context)
            ],
          )),
    );
  }

  Widget _getButtons(List<int> labels, BuildContext context) {
    var listOfButtons = List<Widget>();

    labels.forEach((int label) {
      listOfButtons.add(_getButtonView('Button $label', context, label));
    });

    return Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: listOfButtons);
  }

  Widget _getButtonView(String label, BuildContext context, int index) {
    return GestureDetector(
      child: Container(
        height: 50,
        width: 150,
        margin : EdgeInsets.fromLTRB(15, 25, 15, 20),
        decoration: BoxDecoration(
            color: Colors.blueAccent,
            borderRadius: BorderRadius.all(Radius.circular(10))),
        child: Center(
          child: Text(
            label,
            style: TextStyle(fontWeight: FontWeight.bold),
          ),
        ),
      ),
      onTapDown: (details) {
        onTap(details, context, index);
      },
    );
  }

  onTap(TapDownDetails details, context, int index) {
    var size = MediaQuery.of(context).size;
    var offset = details.globalPosition;

      _overlayEntry?.remove();
    overlayState = Overlay.of(context);

    _overlayEntry = new OverlayEntry(
        builder: (BuildContext context) => Positioned(
            left: offset.dx + 300 >= size.width ? offset.dx - 300 : offset.dx,
            top: offset.dy + 200 >= size.height ? offset.dy - 200 : offset.dy,
            child: Material(
              color: Colors.transparent,
              child: Container(
                  width: 300,
                  height: 200,
                  child: Container(
                      decoration: BoxDecoration(
                          color: Colors.white70,
                          borderRadius: BorderRadius.circular(20),
                          boxShadow: [
                            BoxShadow(
                              color: Colors.grey,
                              blurRadius: 5.0,
                            ),
                          ]),
                      margin: EdgeInsets.symmetric(horizontal: 20),
                      padding: EdgeInsets.fromLTRB(16, 10, 16, 10),
                      child: Wrap(
                        crossAxisAlignment: WrapCrossAlignment.center,
                        alignment: WrapAlignment.center,
                        direction: Axis.vertical,
                        spacing: 10,
                        children: <Widget>[
                          Text(
                            'Main Text',
                            style: TextStyle(
                                fontWeight: FontWeight.bold, fontSize: 25),
                          ),
                          Text('sub text 1'),
                          Text('sub text 2'),
                          Text('sub text 3'),
                          Text('sub text 4')
                        ],
                      ))),
            )));
    overlayState.insert(_overlayEntry);
  }
}
like image 649
krishnaji Avatar asked Nov 10 '19 16:11

krishnaji


People also ask

How do I close the overlay in Flutter?

You'll learn more about ready-to-use public functions that Flutter provides to show dialogs and menus. These functions show route-aware overlays, so you dismiss them by pressing the system back button.

How do you check outside Click in Flutter?

Use Stack() and have a container that will fill the entire screen behind your reaction bar. Use GestureDetector to detect the tap on that container. I'm wrapping the entire screen/body with GestureDetector and used onTapDown to get where the tap has been happened.

How do you overlay the screen in Flutter?

The Overlay in Flutter makes it easy to create visual elements on top of other widgets by adding them to the Overlay's stack. OverlayEntry is used to insert a widget into the Overlay, then Positioned or AnimatedPositioned is used to determine where it will enter within the Overlay.


1 Answers

Wrap the body with Gesture detector, On tap of body the tap event will fire, in tap event method close the overlay as shown in below code

Code:

body: GestureDetector(
  onTap: (){
    _overlayEntry?.remove();
  },
  child : Container(
  height: MediaQuery.of(context).size.height,
  width: MediaQuery.of(context).size.width,
like image 145
Sravya Avatar answered Nov 15 '22 09:11

Sravya