<
Compose学习笔记 路由 导航 页面跳转 `navhost` 和 `navcontroller`
>
上一篇

Flutter 版本共存、版本历史、对应 dart 版本(202410 更新至 flutter 3.24.0)
下一篇

Coroutine 协程 通信 channel sharedflow

Compose 的 路由 导航 页面跳转 NavHostNavController

使用 NavHostNavController 来实现页面跳转、参数传递和返回参数的功能

页面跳转带参数

  1. 设置 NavHost:

NavHost 是导航组件的容器,通常在应用的根 Composable 中定义,通常放在 setContent 函数中

@Composable
fun MyApp() {
    val navController = rememberNavController()  // 创建 NavController
    NavHost(navController, startDestination = "home") {
        composable("home") { HomeScreen(navController) }
        composable("detail/{param}") { backStackEntry ->
            val param = backStackEntry.arguments?.getString("param")
            DetailScreen(navController, param)
        }
    }
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApp()  // 调用 MyApp,开始导航
        }
    }
}
  1. 主页:
@Composable
fun HomeScreen(navController: NavController) {
    Button(onClick = {
        navController.navigate("detail/Hello")
    }) {
        Text("Go to Detail")
    }
}
  1. 详情页:
@Composable
fun DetailScreen(navController: NavController, param: String?) {
    Text("Received param: $param")
    Button(onClick = {
        navController.previousBackStackEntry?.savedStateHandle?.set("result", "Result from Detail")
        navController.popBackStack()
    }) {
        Text("Back with Result")
    }
}

接收返回参数

在主页中,可以通过 savedStateHandle 接收返回的参数:

@Composable
fun HomeScreen(navController: NavController) {
    val backStackEntry = navController.getBackStackEntry("home")
//   val backStackEntry = navController.currentBackStackEntry
    val result = backStackEntry.savedStateHandle.getLiveData<String>("result")

    result.observeAsState().value?.let {
        // 处理返回的参数
    }

    Button(onClick = {
        navController.navigate("detail/Hello")
    }) {
        Text("Go to Detail")
    }
}

关于出栈

popUpTo 在导航到新的页面前,从栈顶开始不断弹出页面直到找到指定页面,inclusive 是否包括指定页面。如果指定页面不存在,则会把所有页面弹出栈

示例:

// 假设栈中存在 `A -> B -> C`
navController.navigate("D") {
    popUpTo("B") { inclusive = true }
}
// 结果是 `A -> D`
// 假设栈中存在 `A -> B -> C`
navController.navigate("D") {
    popUpTo("B") { inclusive = false }
}
// 结果是 `A -> B -> D`
// 假设栈中存在 `A -> B -> C`
navController.navigate("D") {
    popUpTo("Z") { inclusive = false }
}
// 结果是 `D`

其它

关于每个 Screen 需要 参数传递 NavController 的问题

如果页面状态和 NavController 紧密关联,可以通过 Hilt 注入 ViewModel,在 ViewModel 中管理导航逻辑

Top
Foot