Thread
#compose
    Alexander Karkossa

    Alexander Karkossa

    1 year ago
    The new navigation_compose 2.4.0-alpha05 introduced crossfade. At the moment i used "Scaffold per Screen". Each screen in the application has its own Scaffold because some screens should show an docked FAB in the BottomBar. Now, with navigation 2.4.0-alpha05, my blue BottomBar flickers on every navigation, because of the crossfade. I think the solution is to put the scaffold out of the screens -> One global Scaffold Could someone give me an example on how to use the navigation library in compose with one Scaffold around the NavHost. Screen A should not show a fab, Screen B should show the docked FAB. My problem is the fab click handling
    Alexander Karkossa

    Alexander Karkossa

    1 year ago
    Don't think so, but let's hope
    Colton Idle

    Colton Idle

    1 year ago
    I'm also waiting for that next release due to some flickers.
    Francesc

    Francesc

    1 year ago
    in your main composable, where you have the scaffold, you could use this
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    to get the current backstack entry and then, based on this, decide whether to show the FAB or not
    i

    Ian Lake

    1 year ago
    If your bottom bar is part of your destinations, yes, it will crossfade, so you're on the right track on moving shared UI out of each destination and above the NavHost
    Using your current destination as the source of truth for your FAB's location / existence is indeed the recommendation: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1627490432392100?thread_ts=1627477759.324500&cid=CJLTWPH7S
    I'm a big fan of the argument based approach, where you use default values on your arguments to control the global behavior rather than relying on a specific route and tightly coupling them together: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1627400548238900?thread_ts=1627296022.083200&cid=CJLTWPH7S
    Generally, Compose works with state down, events up, so sending events down to a screen feels a bit backward. Maybe having that top level Scaffold own a FabState object that owns the StateMap<NavBackStackEntry,()->Unit> callbacks. Then each screen could use a DisposableEffect to add itself as a listener when it starts being composed and remove itself when it is disposed (i.e., when it is popped or no longer visible)
    Your onClick could then
    lastOrNull { entry -> entry.lifecycle.isAtLeast(Lifecycle.State.RESUMED) }
    to find the only resumed destination to send the click event to (only the current destination is resumed)
    JulianK

    JulianK

    1 year ago
    Sending events down may be bad practice in compose, but you also want to have some encapsulation, right? If my screen shows a list of data and i have a viewmodel that handles this data, this is the place where i can handle the fab button. Handling it all the way up where the NavHost lives (when using a single scaffold) feels wrong, too. Also, if using feature modules, i want to keep the logic inside them and not pull it up to the main module because the NavHost + Scaffold is there. Because "sending events down to a screen feels a bit backward", i decided to move all scaffolds down to the screens, which now breaks because of crossfade.
    btw this applies to other use cases as well, for example when you have buttons in the top bar that are specific to a screen.
    i

    Ian Lake

    1 year ago
    Did you read my suggestion for click events? That still allows individual screens to add a handler for click events without breaking the directionality
    JulianK

    JulianK

    1 year ago
    Yes, thanks. I actually didn't get it was meant as a good solution as events are still send down. Also, i have other cases where screens add additional content to the top bar. One is a tab bar (dynamic count and text) that appears on the same background my TopBar has, the other is a badge that overlaps the Topbar slightly. Both cases are easy with Scaffolds inside screens as i can just modify TopBar content in the screens, but i can't find good and/or easy solutions using a single Scaffold. I'm not even sure it's worth finding another approach, as multiple scaffolds are such a good solution for these cases.
    Ok i finally moved to single scaffold design. Had to animate additional content in the topbar that is changed from screens myself. Another idea to manage custom content outside of the NavHost is described in this article: https://jossiwolf.medium.com/introducing-navigation-material-%EF%B8%8F-a19ed5cc33fd Code: https://gist.github.com/jossiwolf/63732616a9825f1d510c43d23a38d8c5#file-appbottomsheetlayout-kt