Flutter: PopScope ‘canPop’ but won’t pop – How can I fix this?

  Kiến thức lập trình

I am trying to achieve a common outcome that feels like it should be very straightforward: When the user hits the back button the navigation drawer opens, and if they press the back button again, while the drawer is still open, the app closes.

Unfortunately PopScope is not behaving in the way that I would expect it to, and I’m not sure if I’m doing something wrong, or if maybe PopScope has a bug.

//...

class PopScopeAintWorking extends StatelessWidget {
  PopScopeAintWorking ({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: Drawer(
        child: Container(color: Colors.red),
      ),
      body: Builder(builder: (context) {
        return PopScope(
          canPop: Scaffold.of(context).isDrawerOpen,
          onPopInvoked: ((didPop) {
            print("canPop: ${Scaffold.of(context).isDrawerOpen.toString()}");
            print("didPop: ${didPop.toString()}");
            if (!didPop) {
              print("Did not pop.");
              Scaffold.of(context).openDrawer();
            } else {
              print("Pop.");
            }
          }),
          child: PageView(
            physics: const NeverScrollableScrollPhysics(),
            controller: PageController(),
            children: [Container(color: Colors.blue)],
          ),
        );
      }),
    );
  }
}

When the user is viewing PageView.page[0] and taps the Android ‘back’ button twice…

Expected result:
The first time the back button is tapped, canPop: Scaffold.of(context).isDrawerOpen should be ‘false’, so therefore ‘didPop’ should be ‘false’, the app should not pop, and instead the drawer should open.

The second time the back button is tapped, canPop: Scaffold.of(context).isDrawerOpen should be ‘true’, so therefore ‘didPop’ should be ‘true’, and the app should pop.

Actual result:
The first time the back button is tapped, canPop: Scaffold.of(context).isDrawerOpen is ‘false’, so therefore ‘didPop’ is also ‘false’, the app does not pop, and the drawer opens instead.

The second time the back button is tapped, canPop: Scaffold.of(context).isDrawerOpen is ‘true’, but for some reason ‘didPop’ is ‘false’, and the app does not pop.

Console output:
After first tap of the back button:

canPop: false
didPop: false
Did not pop.

After second tap of the back button:

canPop: true
didPop: false
Did not pop.

New contributor

wigley0 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT