Jetpack Compose + Navigation - 使用 BottomNavBar 的嵌套导航

Jetpack Compose + Navigation - Nested navigation with BottomNavBar

我正在尝试使用 Jetpack Compose + Jetpack Navigation 实现以下屏幕流程:

Navigation concept

实际上,我可以编写两个单例代码:

我无法对整个问题进行编码。事实上,我对 NavHost 的管理有疑问。在第一种情况下(SplashScreen -> HomeScreen)我需要在高范围调用 NavHost:

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        MyAppTheme {
            //init the Navigation Controller for screen navigation
            val navController = rememberNavController()

            //setup the Navigation Graph
            SetupNavGraph(navController)

而在第二种情况下,我需要在 Scaffold 可组合项的 innerPadding 范围内调用它:

fun MainScreen(navController: NavHostController) {

    Scaffold(
        bottomBar = {
            BottomNavBar(navController)
        }
    ) { //innerPadding scope
        //setup the Navigation Graph
        SetupNavGraph(navController)
    }
}

请假设 SetupNavGraph() 函数按预期工作(调用 NavHost 生成导航树)

我发现的唯一解决方法是在每个 BottomNav child 选项卡中生成 BottomNavBar 可组合项,但这会产生一个我想避免的可见过渡效果,而且通常不会'这似乎不是一个好习惯。

好的,我找到了解决办法。这是实现预期结果的步骤:

  1. 创建两个不同的 NavGraph,一个用于 Splash->MainScreen,另一个用于 BottomNavBar
const val ROOT_ROUTE = "root"

@Composable
fun SetupRootNavGraph(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = Screen.FirstScreen.route,
        route = ROOT_ROUTE
    ) {
        composable(Screen.FirstScreen.route) { FirstScreen(navController)}
        composable(Screen.SecondScreen.route) { MainScreen(navController)}
    }
}
const val BOTTOM_BAR_ROUTE = "bottomBar"

@Composable
fun SetupNavGraphBottomBar(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = BottomBarScreen.FirstElement.route,
        route = BOTTOM_BAR_ROUTE
    ) {
        composable(BottomBarScreen.FirstElement.route) { FirstElementScreen() }
        composable(BottomBarScreen.SecondElement.route) { SecondElementScreen() }
        composable(BottomBarScreen.ThirdElement.route) { ThirdElementScreen() }
    }
}
  1. MainActivity 中初始化 NavControllersetContent() 之后的 RootNavGraph。这将负责SplashScreen -> MainScreen 导航树。
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyAppTheme {

                //init the Navigation Controller for screen navigation
                val navController = rememberNavController()

                //setup the Root Navigation Graph
                SetupRootNavGraph(navController)
            }
        }
    }
}
  1. Re-init 屏幕中的 NavController 您有 BottomNavBar(示例中的“MainScreen”)并分配给它 innerPadding 中的 BottomNavGraph范围。
@Composable
fun MainScreen(navController: NavHostController) {

    //Re-initialize the NavController to set a new NavGraph
    val navControllerBottomBar = rememberNavController()

    Scaffold(
        bottomBar = {
            BottomNavBar(navControllerBottomBar)
        }
    ) {
        //setup the Navigation Graph
        SetupNavGraphBottomBar(navControllerBottomBar, user)
    }
}

这会很有效!当然,您需要按照 Official docs

中的说明来构建 BottomNavBar 以便管理导航