-
Notifications
You must be signed in to change notification settings - Fork 28.5k
[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
Comments
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. |
Hi @exaby73, Expected: Swipe to go back on "ThirdPage" leads to "Second Page" main.dartimport '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
|
Triage reportI can reproduce this issue with 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")));
}));
}
}
|
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
I found that this bug happens to a lot of apps out there, example: https://omnichess.club/ , as well as my team's 😢 |
This issue is a duplicate of #114324 |
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
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. |
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. |
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. |
This comment was marked as duplicate.
This comment was marked as duplicate.
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. |
I'm using I also added I was hoping to push the user to another page but now I just want to disable it entirely. |
Is this being worked on? It kinda makes ShellRoutes on iOS a no-go |
I was able to find a work around for this issue by wrapping my scaffold in a Example:
The 'Wrapper' build method:
When canPop is false, the swipe back gesture will then render the previous page in the shell route. |
Could you give a more eleborate example @jmason123 ? I can't seem to replicate the fix. Would be really helpfull! |
@rienkkk Sure, this example I used go_router. You'll need to add it as a dependency
|
The workaround suggested by @jmason123 doesn't seem to work when navigating using 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 🤔 |
Expanding on @jmason123 solution I found this to work for us:
|
i'm facing this issue with android as well |
Experiencing this issue as well |
@k-ane Try this solution. We are still utilising it and has been working. Just wrap the shell route page with this.
|
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. |
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? |
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 |
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. |
In my case, using Context: iOS and a mixture of |
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:When including a
ShellRoute
, swipe to go back from "AcknowledgementsPage" will go back to "HomePage" instead of "AboutThisAppPage".The text was updated successfully, but these errors were encountered: