简体   繁体   中英

Flutter: Disable Swipe to Navigate Back in iOS and Android

I'm new to flutter development, and find it a bit frustrating in iOS when you have a navigation drawer and when you swipe to open it, it'll perform a Navigation.of(context).pop() . I would like to disable this "swipe to pop" behavior in iOS. I have been perusing the documentation, but without much luck.

I do see something referred to as aWillPopScope which seems to do the trick ( github issue for it here ), but I'm not 100% sure if this is the "correct" way to do it (it seems too complicated... it should be easier... like a setting on the root app).

WillPopScope is the correct way to do this.

(it seems too complicated... it should be easier... like a setting on the root app).

It is not complicated. It's a one liner :

WillPopScope(
  onWillPop: () async => false,
  child: <children here>
)

A configuration file would make things more complicated as it's harder to read and maintain.

And remember that in flutter everything is a widget not just half of them. Authentification, configurations, everything.

I have one additional point here. I was just solving this problem, but I also needed my user to be able to go back by pressing the "native" back button on the AppBar (did not want to reimplement AppBar just because of this), and I found this niche little flag: userGestureInProgress on the Navigator object, so what I use (and presume is the preferred way) is:

onWillPop: () async {
    if (Navigator.of(context).userGestureInProgress)
      return false;
    else
      return true;
  },

MaterialPageRoute has a parameter called fullscreenDialog which is set to false by default. When true your page animates a bit differently and swipe to go back on iOS will be disabled.

Example usage:

 Navigator.of(context).push(
        MaterialPageRoute(builder: (_) => HomePage(), fullscreenDialog: true));

See some discussion here: https://github.com/flutter/flutter/issues/14203

You can try this in your Widget build:

@override
  Widget build(BuildContext context) {
    return WillPopScope(//forbidden swipe in iOS(my ThemeData(platform: TargetPlatform.iOS,)
      onWillPop: ()async {
        if (Navigator.of(context).userGestureInProgress)
          return false;
        else
          return true;
      },
      child: <your child>,
    );
  }

Alright, so as @Darky said WillPopScope is a perfectly acceptable answer, however, if you want to disable it across the board you can actually do the following.

Open your project in xcode, find AppDelegate.swift and add the following:

let controller: FlutterViewController
    = window?.rootViewController as! FlutterViewController;
controller.navigationController?
    .interactivePopGestureRecognizer?.isEnabled = false;

I had a similar problem where I wanted to block the swipe to return back in navigation (default pop function). This code helped fix the problem.

@override
Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        body: Center(
          child: Text('Example'),
        ),
      ),
    );
  }

This code now blocks the back navigation for iOS & Android (default back button) and that's exactly what I was looking for. Hope this helps.

I am not quite sure what you want to achieve, but most of the time when people want to get rid of the back functionality, because they don't wanna enable the user to control the auth mechanism. For example after the users log in, you don't want them to navigate to the Login page by just press on the back button(or swipe back in iOS). A potential solution is, using pushNamedAndRemoveUntil .

Future<T> pushNamedAndRemoveUntil<T extends Object>(BuildContext context, String newRouteName, RoutePredicate predicate)

Push the route with the given name onto the navigator that most tightly encloses the given context, and then remove all the previous routes until the predicate returns true.

Example code: pushNamedAndRemoveUntil(context, '/home', ModalRoute.withName('/home'));

Note: use this method to some certain extent, because you might mess up your navigation history.

Whenever the back button or Swipe gesture(iOS) is pressed, you will get a callback at onWillPop , which returns a Future . If the Future returns true, the screen is popped(ie navigate to the previous screen), If it is false, then it doesn't navigate back.

Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
        return Future.value(false);
      },
      child: Scaffold(
        appBar: AppBar(title: Text("Second Screen"),),
        body: Center(

And if you want to pop screen on a condition basis then declare

bool shouldPop = true; // change this using setState() inside build on the requirement. 

  onWillPop: () {
        return Future.value(shouldPop? true: false);
      },

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM