Nested navigation

TabNavigator + Navigator

For more complex use cases, when each tab should have its own independent navigation, like the Youtube app, you can combine the TabNavigator with multiple Navigators.

Let's go back to the Tab navigation example.

setContent {
    TabNavigator(HomeTab) {
        // ...
    }
}

But now, the HomeTab will have it's own Navigator.

object HomeTab : Screen {

    @Composable
    override fun Content() {
        Navigator(PostListScreen())
    }
}

That way, we can use the LocalNavigator to navigate deeper into HomeTab, or the LocalTabNavigator to switch between tabs.

class PostListScreen : Screen {

    @Composable
    private fun GoToPostDetailsScreenButton(post: Post) {
        val navigator = LocalNavigator.currentOrThrow
        
        Button(
            onClick = { navigator.push(PostDetailsScreen(post.id)) }
        )
    }

    @Composable
    private fun GoToProfileTabButton() {
        val tabNavigator = LocalTabNavigator.current

        Button(
            onClick = { tabNavigator.current = ProfileTab }
        )
    }
}

Nested Navigators

Going a little further, it's possible to have nested navigators. The Navigator has a level property (so you can check how deeper your are) and can have a parent navigator (if you need to interact with it).

setContent {
    Navigator(ScreenA) { navigator0 ->
        println(navigator.level)
        // 0
        println(navigator.parent == null)
        // true
        Navigator(ScreenB) { navigator1 ->
            println(navigator.level)
            // 1
            println(navigator.parent == navigator0)
            // true
            Navigator(ScreenC) { navigator2 ->
                println(navigator.level)
                // 2
                println(navigator.parent == navigator1)
                // true
            }
        }
    }
}

Another operation is the popUntilRoot(), it will recursively pop all screens starting from the leaf navigator until the root one.

Sample

Source code here.

Last updated