Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[go_router] ShellRoutes break iOS swipe back navigation #120353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
mnefzger opened this issue Feb 9, 2023 · 30 comments
Open

[go_router] ShellRoutes break iOS swipe back navigation #120353

mnefzger opened this issue Feb 9, 2023 · 30 comments
Labels
found in release: 3.7 Found to occur in 3.7 found in release: 3.8 Found to occur in 3.8 has reproducible steps The issue has been confirmed reproducible and is ready to work on p: go_router The go_router package P2 Important issues not at the top of the work list package flutter/packages repository. See also p: labels. platform-ios iOS applications specifically team-go_router Owned by Go Router team triaged-go_router Triaged by Go Router team

Comments

@mnefzger
Copy link

mnefzger commented Feb 9, 2023

go_router version: 6.0.4
flutter version: 3.3.9

Hi go_router team,
we experience an unexpected behaviour when it comes to using GoRouter with ShellRoutes in combination with the iOS "swipe to go back" gesture. The navigation seems to skip over all routes wrapped in the ShellRoute. Everything works as expected with the Android "swipe to go back" gesture.

Steps to Reproduce

With the below code sample using a ShellRoute, navigate to sub-page "AcknowledgementsPage" and then "swipe to go back" on iOS.

Expected results: Navigation goes back only one page to "AboutThisAppPage".

Actual results: Navigation skips any page wrapped in ShellRoute, goes back to "HomePage".

Code sample With this example, the "swipe to go back" works as expected:
GoRouter(
      initialLocation: '/home',
      routes: [
        GoRoute(
          path: '/home',
          name: HomePage.routeName,
          pageBuilder: const HomePage(),
          routes: [
             GoRoute(
                path: 'about',
                name: AboutThisAppPage.routeName,
                pageBuilder: const AboutThisAppPage(),
                routes: [
                  GoRoute(
                      path: 'acknowledgements',
                      name: AcknowledgementsPage.routeName,
                      pageBuilder: const AcknowledgementsPage(),
                  ),
                ]),
          ])
       ]);

When including a ShellRoute, swipe to go back from "AcknowledgementsPage" will go back to "HomePage" instead of "AboutThisAppPage".

GoRouter(
    initialLocation: '/home', 
    routes: [
     GoRoute(
        path: '/home',
        name: HomePage.routeName,
        pageBuilder: const HomePage(),
        routes: [
          // This minimal ShellRoute does not provide any benefit but is enough to reproduce the unexpected behaviour
          ShellRoute(
            builder: (context, state, child) {
              return child;
            },
            routes: [
              GoRoute(
                  path: 'about',
                  name: AboutThisAppPage.routeName,
                  pageBuilder: const AboutThisAppPage(),
                  routes: [
                    GoRoute(
                      path: 'acknowledgements',
                      name: AcknowledgementsPage.routeName,
                      pageBuilder: const AcknowledgementsPage(),
                    ),
                  ]),
            ]
          )
        ])
  ]);
@exaby73 exaby73 added the in triage Presently being triaged by the triage team label Feb 9, 2023
@exaby73
Copy link
Member

exaby73 commented Feb 9, 2023

Hello @mnefzger. Thank you for filing this issue. Can you please provide the following information?

Please provide the information in the form of text. See how to make collapsible sections with Markdown here.

@exaby73 exaby73 added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Feb 9, 2023
@mnefzger
Copy link
Author

mnefzger commented Feb 9, 2023

Hi @exaby73,
sure – sorry for not adding a full example from the start.

Expected: Swipe to go back on "ThirdPage" leads to "Second Page"
Actual: Leads back to "HomePage"

main.dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
        routerConfig: GoRouter(initialLocation: '/home', routes: [
      GoRoute(
          path: '/home',
          name: 'home',
          pageBuilder: const HomePage(),
          routes: [
            // This minimal ShellRoute does not provide any benefit but is enough to reproduce the unexpected behaviour
            ShellRoute(
                builder: (context, state, child) {
                  return child;
                },
                routes: [
                  GoRoute(
                      path: 'second',
                      name: 'second',
                      pageBuilder: const SecondPage(),
                      routes: [
                        GoRoute(
                          path: 'third',
                          name: 'third',
                          pageBuilder: const ThirdPage(),
                        ),
                      ]),
                ])
          ])
    ]));
  }
}

class HomePage {
  const HomePage();

  static void goTo(BuildContext context) {
    context.goNamed('home');
  }

  Page call(BuildContext context, GoRouterState routerState) {
    return MaterialPage(child: Builder(builder: (context) {
      return Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text("Home Page"),
              OutlinedButton(
                  onPressed: () => SecondPage.goTo(context),
                  child: const Text("Go To Second")),
            ],
          ),
        ),
      );
    }));
  }
}

class SecondPage {
  const SecondPage();

  static void goTo(BuildContext context) {
    context.goNamed('second');
  }

  Page call(BuildContext context, GoRouterState routerState) {
    return MaterialPage(child: Builder(builder: (context) {
      return Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text("Second Page"),
              OutlinedButton(
                  onPressed: () => ThirdPage.goTo(context),
                  child: const Text("Go To Third")),
            ],
          ),
        ),
      );
    }));
  }
}

class ThirdPage {
  const ThirdPage();

  static void goTo(BuildContext context) {
    context.goNamed('third');
  }

  Page call(BuildContext context, GoRouterState routerState) {
    return MaterialPage(child: Builder(builder: (context) {
      return const Scaffold(body: Center(child: Text("Third Page")));
    }));
  }
}
flutter doctor -v
[✓] Flutter (Channel stable, 3.3.9, on macOS 13.0.1 22A400 darwin-arm, locale en-DE)
    • Flutter version 3.3.9 on channel stable at /Users/matthias.nefzger/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision b8f7f1f986 (3 months ago), 2022-11-23 06:43:51 +0900
    • Engine revision 8f2221fbef
    • Dart version 2.18.5
    • DevTools version 2.15.0

[!] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/matthias.nefzger/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.

[✓] Xcode - develop for iOS and macOS (Xcode 14.0.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14A400
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] VS Code (version 1.71.2)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.56.0

Scanning for devices is taking a long time...[✓] Connected device (1 available)
    • iPhone 13 Pro Max (mobile) • 26B46424-9068-4C85-BD99-D0F1B45959F7 • ios            • com.apple.CoreSimulator.SimRuntime.iOS-16-0 (simulator)

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.

@github-actions github-actions bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Feb 9, 2023
@exaby73
Copy link
Member

exaby73 commented Feb 10, 2023

Triage report

I can reproduce this issue with Master (3.8.0-9.0.pre.20)

Code Sample (Same as OP)
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
        routerConfig: GoRouter(initialLocation: '/home', routes: [
      GoRoute(
          path: '/home',
          name: 'home',
          pageBuilder: const HomePage(),
          routes: [
            // This minimal ShellRoute does not provide any benefit but is enough to reproduce the unexpected behaviour
            ShellRoute(
                builder: (context, state, child) {
                  return child;
                },
                routes: [
                  GoRoute(
                      path: 'second',
                      name: 'second',
                      pageBuilder: const SecondPage(),
                      routes: [
                        GoRoute(
                          path: 'third',
                          name: 'third',
                          pageBuilder: const ThirdPage(),
                        ),
                      ]),
                ])
          ])
    ]));
  }
}

class HomePage {
  const HomePage();

  static void goTo(BuildContext context) {
    context.goNamed('home');
  }

  Page call(BuildContext context, GoRouterState routerState) {
    return MaterialPage(child: Builder(builder: (context) {
      return Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text("Home Page"),
              OutlinedButton(
                  onPressed: () => SecondPage.goTo(context),
                  child: const Text("Go To Second")),
            ],
          ),
        ),
      );
    }));
  }
}

class SecondPage {
  const SecondPage();

  static void goTo(BuildContext context) {
    context.goNamed('second');
  }

  Page call(BuildContext context, GoRouterState routerState) {
    return MaterialPage(child: Builder(builder: (context) {
      return Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text("Second Page"),
              OutlinedButton(
                  onPressed: () => ThirdPage.goTo(context),
                  child: const Text("Go To Third")),
            ],
          ),
        ),
      );
    }));
  }
}

class ThirdPage {
  const ThirdPage();

  static void goTo(BuildContext context) {
    context.goNamed('third');
  }

  Page call(BuildContext context, GoRouterState routerState) {
    return MaterialPage(child: Builder(builder: (context) {
      return const Scaffold(body: Center(child: Text("Third Page")));
    }));
  }
}
flutter doctor -v (Master)
[!] Flutter (Channel master, 3.8.0-9.0.pre.20, on macOS 13.2 22D49 darwin-arm64, locale en-US)
    • Flutter version 3.8.0-9.0.pre.20 on channel master at /Users/nabeelparkar/fvm/versions/master
    ! Warning: `dart` on your path resolves to /opt/homebrew/Cellar/dart/2.19.1/libexec/bin/dart, which is not inside your current Flutter SDK checkout at /Users/nabeelparkar/fvm/versions/master. Consider adding /Users/nabeelparkar/fvm/versions/master/bin to the front of your path.
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 001c4951b6 (7 hours ago), 2023-02-09 20:14:10 -0500
    • Engine revision e1d0032029
    • Dart version 3.0.0 (build 3.0.0-218.0.dev)
    • DevTools version 2.21.1
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/nabeelparkar/Library/Android/sdk/
    • Platform android-33, build-tools 33.0.0
    • ANDROID_SDK_ROOT = /Users/nabeelparkar/Library/Android/sdk/
    • Java binary at: /Users/nabeelparkar/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/221.6008.13.2211.9477386/Android Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • CHROME_EXECUTABLE = /Applications/Brave Browser.app/Contents/MacOS/Brave Browser

[✓] Android Studio (version 2021.3)
    • Android Studio at /Users/nabeelparkar/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/213.7172.25.2113.9123335/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] Android Studio (version 2022.1)
    • Android Studio at /Users/nabeelparkar/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/221.6008.13.2211.9477386/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.15+0-b2043.56-8887301)

[✓] VS Code (version 1.75.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.58.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 13.2 22D49 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Brave Browser 110.1.48.158

[✓] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 1 category.

@exaby73 exaby73 added platform-ios iOS applications specifically package flutter/packages repository. See also p: labels. has reproducible steps The issue has been confirmed reproducible and is ready to work on p: go_router The go_router package found in release: 3.7 Found to occur in 3.7 found in release: 3.8 Found to occur in 3.8 labels Feb 10, 2023
@darshankawar darshankawar removed the in triage Presently being triaged by the triage team label Feb 13, 2023
@stuartmorgan-g stuartmorgan-g added the P2 Important issues not at the top of the work list label Feb 14, 2023
@MrLightful

This comment was marked as duplicate.

@mnefzger

This comment was marked as duplicate.

@luisgurmendez
Copy link

luisgurmendez commented Mar 24, 2023

I found that this bug happens to a lot of apps out there, example: https://omnichess.club/ , as well as my team's 😢

@luisgurmendez
Copy link

This issue is a duplicate of #114324

@trushchinskiy

This comment was marked as duplicate.

@decaf-dev

This comment was marked as duplicate.

@flutter-triage-bot flutter-triage-bot bot added multiteam-retriage-candidate team-go_router Owned by Go Router team triaged-go_router Triaged by Go Router team labels Jul 8, 2023
@RafaelZasas
Copy link

Has there been any updates onto this? I’m still facing the same issue. My app is wrapped in a shell route to persist bottom navigation bar so there is no back swiping at all.

@valentinozegna
Copy link

I am having the same exact issue with StatefulShellRoute.indexedStack. I use it for the bottom NavigationBar and I have various routes nested inside StatefulBranches. This completely broke the swipe back behavior on Android, however it is still functional on iOS.

@revenpl
Copy link

revenpl commented Oct 29, 2023

This issue is a duplicate of #114324

We have the same issue, on native iOS app. This is not a duplicate. Calling context.pop() is popping to correct destination but back swipe gesture on iOS is navigating to incorrect route. The same back gesture on Android is working correctly.

We did not find any solution to solve this problem. We assigned GlobalKeys to every ShellRoute in our app, and the behaviour is inconsistent between platforms, so I do not think it is a problem with our code.

@joseluisonelife

This comment was marked as duplicate.

@straygar
Copy link

straygar commented Feb 7, 2024

Did anybody manage to come up with a workaround? I'm in the same boat as one of the commenters - using ShellRoute to maintain a bottom navbar, but this causes backswipes to close the app instead doing the expected thing.

@enchance
Copy link

enchance commented Mar 1, 2024

I'm using StatefulShellRoute.indexedStack() and whenever the back button is pressed when showing the toplevel StatefulShellBranch the app closes. I tried adding PopScope(canPop: false) but it still closes the app. Any workarounds for this?

I also added android:enableOnBackInvokedCallback="false" to android/app/src/main/res/AndroidManifest.xml and it still doesn't work.

I was hoping to push the user to another page but now I just want to disable it entirely.

@alfalcon90
Copy link

Is this being worked on? It kinda makes ShellRoutes on iOS a no-go

@jmason123
Copy link

jmason123 commented Apr 18, 2024

I was able to find a work around for this issue by wrapping my scaffold in a PopScope and then conditionally setting canPop.

Example:

ShellRoute(
            builder: (_, __, child) => Wrapper(child: child),

The 'Wrapper' build method:

@override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: currentStep == 0,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('App bar title'),
        ),
        body: widget.child,
      ),
    );
  }

When canPop is false, the swipe back gesture will then render the previous page in the shell route.

@rienkkk
Copy link

rienkkk commented Apr 23, 2024

Could you give a more eleborate example @jmason123 ? I can't seem to replicate the fix. Would be really helpfull!

@jmason123
Copy link

jmason123 commented Apr 23, 2024

@rienkkk Sure, this example I used go_router. You'll need to add it as a dependency go_router: 13.2.0

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  runApp(
    MaterialApp.router(
      theme: ThemeData(
        brightness: Brightness.dark,
        appBarTheme: const AppBarTheme(
          backgroundColor: Colors.blue,
        ),
        floatingActionButtonTheme: const FloatingActionButtonThemeData(
          backgroundColor: Colors.blue,
        ),
      ),
      routerConfig: GoRouter(
        initialLocation: '/landing-page',
        routes: [
          GoRoute(
              path: '/landing-page',
              builder: (_, __) {
                return const LandingPage();
              }),
          ShellRoute(
            builder: (_, __, child) => ScaffoldWithNavBar(child: child),
            routes: [
              GoRoute(
                path: '/screen-1',
                builder: (_, __) {
                  return const Screen1();
                },
              ),
              GoRoute(
                path: '/screen-2',
                builder: (_, __) {
                  return const Screen2();
                },
              ),
              GoRoute(
                path: '/screen-3',
                builder: (_, __) {
                  return const Screen3();
                },
              ),
            ],
          ),
        ],
      ),
    ),
  );
}

class ScaffoldWithNavBar extends StatelessWidget {
  const ScaffoldWithNavBar({super.key, required this.child});

  final Widget child;

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: GoRouterState.of(context).uri.path == '/screen-1',
      child: Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          leading: IconButton(
            icon: const Icon(Icons.arrow_back),
            onPressed: () => context.pop(),
          ),
          title: const Text('App bar title'),
        ),
        body: child,
      ),
    );
  }
}

class LandingPage extends StatelessWidget {
  const LandingPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('landing page'),
            OutlinedButton(
                onPressed: () => context.push('/screen-1'),
                child: const Text('to screen 1'))
          ],
        ),
      ),
    );
  }
}

class Screen1 extends StatelessWidget {
  const Screen1({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          const Text('on screen 1'),
          OutlinedButton(
              onPressed: () => context.push('/screen-2'),
              child: const Text('to screen 2'))
        ],
      ),
    );
  }
}

class Screen2 extends StatelessWidget {
  const Screen2({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          const Text('on screen 2'),
          OutlinedButton(
              onPressed: () => context.push('/screen-3'),
              child: const Text('to screen 3'))
        ],
      ),
    );
  }
}

class Screen3 extends StatelessWidget {
  const Screen3({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Column(
        children: [
          Text('on screen 3'),
        ],
      ),
    );
  }
}

@pavlo-zin
Copy link

The workaround suggested by @jmason123 doesn't seem to work when navigating using goNamed() or goTo().

Has anyone found a working solution? This issue is critical, even for relatively small apps. I’m wondering why it’s taking more than 477 days to resolve this 🤔

@Rimantovas
Copy link

Expanding on @jmason123 solution I found this to work for us:

class Wrapper extends StatelessWidget {
  const Wrapper({
    super.key,
    required this.child,
  });
  final Widget child;

  bool canPop(BuildContext context) {
    final lastMatch = GoRouter.of(context)
        .routerDelegate
        .currentConfiguration
        .matches
        .lastOrNull;

    if (lastMatch is ShellRouteMatch) {
      return lastMatch.matches.length == 1;
    }
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: canPop(context),
      child: child,
    );
  }
}

@cracker-source
Copy link

i'm facing this issue with android as well

@k-ane
Copy link

k-ane commented Oct 12, 2024

Experiencing this issue as well

@Rimantovas
Copy link

@k-ane Try this solution. We are still utilising it and has been working. Just wrap the shell route page with this.

Expanding on @jmason123 solution I found this to work for us:

class Wrapper extends StatelessWidget {
  const Wrapper({
    super.key,
    required this.child,
  });
  final Widget child;

  bool canPop(BuildContext context) {
    final lastMatch = GoRouter.of(context)
        .routerDelegate
        .currentConfiguration
        .matches
        .lastOrNull;

    if (lastMatch is ShellRouteMatch) {
      return lastMatch.matches.length == 1;
    }
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: canPop(context),
      child: child,
    );
  }
}

@MarpinLL
Copy link

MarpinLL commented Jan 9, 2025

Based on the examples I've seen in the comments, using context.goNamed() prevents pages from being added to the stack. This means there are no pages to go back to, so context.pop() doesn't work and swipe gestures are disabled. However, if you use context.pushNamed() instead, it works properly. context.goNamed() should be used when you don't want to allow returning to the previous page.

@juandpt03
Copy link

I am using StatefulShellRoute.indexedStack and on IOS when I use the gestures to go back it doesn't work, on Android it behaves fine, why hasn't this been solved yet?

@karroze
Copy link

karroze commented Apr 8, 2025

This package is full of bugs, questionable decisions by the team and workarounds to make it operate somewhat properly. Absolutely hideous to have a "Flutter Favorite" bage

@juandpt03
Copy link

I was able to fix it and forgot to mention that this bug occurs when using custom transitions. You need to adjust your code so that Cupertino transitions are used on iOS instead of the custom ones.

@mk-wang
Copy link

mk-wang commented Apr 19, 2025

I was able to fix it and forgot to mention that this bug occurs when using custom transitions. You need to adjust your code so that Cupertino transitions are used on iOS instead of the custom ones.

You are quite right; employing the standard Cupertino transitions is a valid approach.
Alternatively, should the implementation necessitate custom transitions, ensure the createRoute method is overridden to return a PageRoute incorporating the CupertinoRouteTransitionMixin.

@helgoboss
Copy link

helgoboss commented May 6, 2025

I was able to fix it and forgot to mention that this bug occurs when using custom transitions. You need to adjust your code so that Cupertino transitions are used on iOS instead of the custom ones.

In my case, using CupertinoPageRoute/CupertinoPage instead of MaterialPageRoute/MaterialPage everywhere doesn't fix it. But #120353 (comment) fixes it. Thanks!

Context: iOS and a mixture of ShellRoute and StatefulShellRoute (on Android it works nicely)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
found in release: 3.7 Found to occur in 3.7 found in release: 3.8 Found to occur in 3.8 has reproducible steps The issue has been confirmed reproducible and is ready to work on p: go_router The go_router package P2 Important issues not at the top of the work list package flutter/packages repository. See also p: labels. platform-ios iOS applications specifically team-go_router Owned by Go Router team triaged-go_router Triaged by Go Router team
Projects
No open projects
Status: No status
Development

No branches or pull requests