csells / go_router

The purpose of the go_router for Flutter is to use declarative routes to reduce complexity, regardless of the platform you're targeting (mobile, web, desktop), handling deep linking from Android, iOS and the web while still allowing an easy-to-use developer experience.
https://gorouter.dev
441 stars 97 forks source link

Android system back button or navigation back gesture always pops entire app #57

Closed rydmike closed 3 years ago

rydmike commented 3 years ago

When popping routes that have been routed to as sub-routes or via push, it is expected that Android system back button or system navigation back swipe, would pop back to previous screen, until we are back on start screen, after which the app would be popped. However, in all GoRouter examples the Android back button or back navigation gesture, always directly pops the entire app.

This can be demonstrated e.g. with example sub_routes.dart:

or with example push.dart:


I have not yet tried to figure out why this happens 😃

csells commented 3 years ago

yep. that's a bug alright. the Android Back button should work the same as the AppBar Back button.

rydmike commented 3 years ago

Actually Android back button and browser back do not and should not behave the same.

Web back is always chronological back, while back on app bar and and on Android system back button or back swipe gesture, is "always" up. But it is not that simple, to go down the rabbit hole, here is good read on the topic:

https://github.com/tomgilder/routemaster/issues/176#issuecomment-881859680

TLDR: It's a mess.

masreplay commented 3 years ago

yep. that's a bug alright. the Android Back button should work the same as the AppBar Back button.

when we will get the fixes please

esDotDev commented 3 years ago

Actually Android back button and browser back do not and should not behave the same.

Web back is always chronological back, while back on app bar and and on Android system back button or back swipe gesture, is "always" up. But it is not that simple, to go down the rabbit hole, here is good read on the topic:

tomgilder/routemaster#176 (comment)

TLDR: It's a mess.

Well back on the web is just a deeplink, inside a chronological array of deeplinks that the browser maintains, it doesn't really have any relation to System Back or a UI back button.

I think this is generally correct that Android Back should work the same as AppBar back, but we should also be able to intercept it, in case we have some fullscreen popup (path-less), or maybe a widget that has it's own internal "back" handler.

SunlightBro commented 3 years ago

No a big issue actually, just missed to pass _key to the Navigator 😉.

csells commented 3 years ago

fixed in v2.0.0. @rydmike @masreplay please verify.

rydmike commented 3 years ago

Works great in my tests. Issue can imo be closed.

And yes the Android back button works like the AppBar back button now, while browser back retains its chronological order as it should, this all checks out now. -> OK -> CLOSE


Related to this topic but not to the issue

The big controversy about the Android back is regarding what should happen when you press the Android back button and you have a bunch top level bottom navigation destinations, but are not on the 1st destination.

Strictly behaving like the AppBar back, would mean popping the app, since there is no AppBar back on the stack, since we are at a top level already.

This is the past default behavior, but few apps does that anymore, because it is poor UX. Not even Google's apps does this.

Below I collected some samples about what different apps does in this situation.

I still consider the above current implementation correct, and the alternative nicer behavior like 2 and 3 below better UX. However, those can be implemented as custom behavior on the top destinations, to only pop app via 1st and move to it if not on 1st and/or maintain a stack of visited unique top destinations before back to 1. Both work, as long as the app is not popped when the user is not on the 1st usual "home" destination. Still, it does not have to be supported directly by go_router imo, as far as I can see you can still build patterns 2 and 3 below if you want it with the go_router as well.


The Unbearable Lightness of the Android Back Button

I started looking at what "big" (well some) apps do on Android on bottom nav or main nav pattern it uses, when using system back button or back swipe function. I had not though so much about it before, but gosh did I find a can of worms.

1. Always pops entire app, regardless of where you are on bottom destination

2. If not on 1st destination, goes to 1st, then pops app.

When on 1st destination, these always pops the app, but only from 1st one.

I used this in an app, because I disliked 1 so much and this was simple to add. Just a, if not on 1, then move there if the app tries to pop itself, if on one, then fine go ahead pop app.

3. Keep unique visited destinations on a stack equal to nr of bottom destinations, pop back in last used unique order, when nothing left, if not on 1, then back to 1, then pop app

To mention a few. I rather like this one actually, but 2 is fine as well imo.

4. Keep N unique destinations, then pop the app.

Usually N is equal to nr of bottom destination. Pop them until nothing remains, then pop app. The app can thus be popped from other than 1st destination, depends on how you navigated on bottom navbar

5. Keep entire bottom nav history.

Just keep them all on a stack and pop back in order until nothing remains, then pop app. Since you started on 1, you eventually end up popping the app from 1.

Have you found any other patterns?

Why use back button/swipe on Android with bottom navbars?

Some claim they never navigate with the back button/swipe on Android in apps with bottom navbars.

I do it all the time. Why?

When I hold the phone with one handed grip with my right hand in the lower right corner, I can't reach the 1st destination with my thumb without using very uncomfortable and wobbly phone tilting action to reach it, so I just swipe back with my thumb to get there. I expect it to get to 1st destination at some point, like in cases 2, 3 and 5.

If the app then does pattern 1) it is really the worst UX of them all. Hue that I use a lot makes me wanna scream in frustration. Case 4 is just weird, but you might not notice its weirdness unless you really look for it and create a back stack that shows it, but when it happens it is a bit of a WTF moment.