kotlinandroid-jetpack-composejetpack-compose-navigationandroid-jetpack-compose-navigation

Jetpack Compose popBackStack problems with animated navigation transitions


When using new Compose navigation that incorporates animations in NavHost by default, i encountered a few issues with navController.popBackStack(). (Edit 2: nav version 2.8.0-beta03)

2 main issues were:

  1. Navigating to blank screen when double tapping on back button that invokes popBackStack()
  2. Invoking popBackStack() before navigation animation to new screen is finished leads to new route being popped from stack but screen remains and sometimes overlaps with underlying screen.

I was able to resolve both issues by checking navigation lifecycle before invoking popBackStack() with below code:

if(navController.currentBackStackEntry?.lifecycle?.currentState == Lifecycle.State.RESUMED) {
    navController.popBackStack()
}

Now everything works, except now I can not invoke popBackStack() before animation is finished which leads to some clunky behaviour where users can not navigate back for 700-1000ms due to lifecycle not being in RESUMED state immediately after the screen is shown (due to default crossfade animation lasting around 700 ms default)

I checked to see how system back button behaves in this scenario and I never encountered any of the 2 problems listed above, moreover I am able to navigate back immediately after navigating forward without the need to wait for RESUMED lifecycle without any of the issues listed above.

I checked the NavHost implementation and the only thing they do is implement BackHandler that has navController.popBackStack() in there so I am wondering if the fix i made is the correct way of popping the stack.

I would like for my back buttons to behave same as system back presses without removing default navigation animations.

Any info on the topic is appreciated, as i was unable to find anything useful in official documentation on how to tackle this issue.

Edit 1: To provide more context to the second issue, as it is more breaking, I am providing a picture of the issue below:

Issue 2

My back stack is:

ScreenA -> ScreenB -> ScreenC -> ScreenD

then i do navController.popBackStack()

Then my back stack becomes:

ScreenA -> ScreenB -> ScreenC (-> ScreenD still partially visible)

Basically, screen D is white with title "Screen D" on top center, and screen C is yellow with title "Screen C" in the middle. When invoking navController.popBackStack() before crossfade nav animation from C to D finishes, screen D gets popped from back stack, but remains on screen and due to crossfade alpha it overlaps with actual current screen, that being screen C.


Solution

  • I like to know which navigation compose version do you use, if you use new typesafe navigation compose version: 2.8.0-beta03, or 2.8.0-beta01 or the version that 2.8.0-alpha08 introduce Safe Args in Navigation Compose, these version has some weird bug in the library itself, espicially in popping the backstack.

    If we use navController.popBackStack or navController.navigateUp to navigate back to our previous screen, it sometime navigate back, sometimes not just stuck

    To resolve this issue, move to the stable navigation compose version which is 2.7.7 so far.

    I already reported this bug on issue tracker, btw not only me but many other See: https://issuetracker.google.com/issues/347114499