Search code examples
androidflutternavigatorshowdialogsimpledialog

Navigator.pop won't close the simpledialog in flutter


I'm building android app using flutter. I have a problem to close the simple dialog programmatically.

Now I have a stateful page named ListVessel. This page contains listTile from array otherVessels.
Below is the code for this page.

class ListVessel extends StatefulWidget {
  final Function() notifyParent;
  ListVessel({Key key, @required this.notifyParent}) : super(key: key);

  @override
  _ListVesselState createState() => _ListVesselState();
}

class _ListVesselState extends State<ListVessel> {
  @override
  Widget build(BuildContext context) {
      return ListView.separated(
        separatorBuilder: (context, index) => Divider(color: Colors.blueGrey),
        itemCount: otherVessels.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text("Name: "+otherVessels[index]["shipName"]),
            onTap: () {
              showDialog (
                  context: context,
                  builder: (_){
                    return otherTap(idx:index);
                  }
              );
            }
          );
        },
      );
    }
  }
}

From above code, each tile (vessel) can be tapped and it calls otherTap() method. otherTap() method displays a simple dialog (popup) that contains the details of the tapped vessel.
Below is the code for otherTap().

class otherTap extends StatefulWidget{
  otherTap({Key key, @required this.idx}) : super(key: key);
  final int idx;
  @override
  _otherTapState createState() => new _otherTapState();
}

class _otherTapState extends State<otherTap>{
  @override
  Widget build(BuildContext context){
  _isDialogShowing = true;
       return SimpleDialog(
        title: Text(otherVessels[widget.idx]["shipName"]),
        children: <Widget>[
          SimpleDialogOption(
            child: Text('MMSI : ' + otherVessels[widget.idx]['MMSI']),
          )
        ],
      );
  }
}

I have a global boolean variable (_isDialogShowing) to keep tracking if the dialog is showing.
Now i want the showdialog (popup) to dismiss after 5 second.
I use Navigator.pop() to dismiss the dialog in the MyApp function. I put it inside setstate() function.

void main() {
  runApp(
    MyApp(storage: CounterStorage()),
  );
}

class MyApp extends StatefulWidget {
  MyApp({Key key, @required this.storage}) : super(key: key);
  final CounterStorage storage;
  @override
  State<StatefulWidget> createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
  final appTitle = 'Testing applicatin';

  void _update(BuildContext context) async {
    await Future.delayed(Duration(milliseconds: 5000));

    setState(() {
      if(_isDialogShowing){
        _isDialogShowing = false;
         Navigator.pop(context);
         //Navigator.of(context).pop();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    _update(context);
    return new WillPopScope(
      onWillPop:  null,
      child: new MaterialApp(
        debugShowCheckedModeBanner: false,
        title: appTitle,
        home: MyHomePage(title: appTitle),
        routes: {
          Routes.home: (context) => MyHomePage(),
          Routes.settings: (context) => SettingsPage(),
        },
      ),
    );
  }
}

However the navigator.pop methods above doesn't close the popup.
Can anyone help?


Solution

  • You need to call pop on the context that you receive in builder of showDialog(), only then the dialog will pop that was created by that showDialog().

    Replace your showDialog() with following and it will work for you:

    showDialog(
      context: context,
      builder: (BuildContext context) {
        Future.delayed(Duration(seconds: 5)).then((_) {
          Navigator.pop(context);
        });
        return otherTap(idx:index);
      },
    );