Tab navigation

To use the TabNavigator you should first import cafe.adriel.voyager:voyager-tab-navigator (see Setup).

Voyager provides a specialized navigator for tabs : the TabNavigator.

The Tab interface, like the Screen, has a Content() composable function, but also requires a TabOptions.

object HomeTab : Tab {

    override val options: TabOptions
        @Composable
        get() {
            val title = stringResource(R.string.home_tab)
            val icon = rememberVectorPainter(Icons.Default.Home)

            return remember {
                TabOptions(
                    index = 0u,
                    title = title,
                    icon = icon
                )
            }
        }

    @Composable
    override fun Content() {
        // ...
    }
}

Since tabs aren't usually reused, its OK to create them as object.

The TabNavigator unlike the Navigator:

  • Don't handle back presses, because the tabs are siblings

  • Don't implements the Stack API, just provides a current property

You can use it with a Scaffold to easily create the UI for your tabs.

setContent {
    TabNavigator(HomeTab) {
        Scaffold(
            content = { 
                CurrentTab() 
            },
            bottomBar = {
                BottomNavigation {
                    TabNavigationItem(HomeTab)
                    TabNavigationItem(FavoritesTab)
                    TabNavigationItem(ProfileTab)
                }
            }
        )
    }
}

Like theCurrentScreen(), you should use CurrentTab instead of tabNavigator.current.Content(), because it will save the Tab's subtree for you (see SaveableStateHolder).

Use the LocalTabNavigator to get the current TabNavigator, and current to get and set the current tab.

@Composable
private fun RowScope.TabNavigationItem(tab: Tab) {
    val tabNavigator = LocalTabNavigator.current

    BottomNavigationItem(
        selected = tabNavigator.current == tab,
        onClick = { tabNavigator.current = tab },
        icon = { Icon(painter = tab.icon, contentDescription = tab.title) }
    )
}

Sample

Source code here.

Last updated