繁体   English   中英

如何使用 navController 在 Jetpack Compose 中从一个屏幕导航到另一个屏幕?

[英]How to navigate from a screen to another in Jetpack Compose using navController?

我有这样的结构:

val navController = rememberNavController()
NavHost(
    navController = navController,
    startDestination = "auth"
) {
    composable(
        route = "auth"
    ) {
        AuthScreen(
            navController = navController
        )
    }
    composable(
        route = "profile"
    ) {
        ProfileScreen(
            navController = navController
        )
    }
}

当我第一次打开应用程序时,根据身份验证 state 显示一个屏幕:

if (!viewModel.isUserAuthenticated) {
    AuthScreen(navController = navController)
} else {
    ProfileScreen(navController = navController)
}

哪个工作正常。 问题来了,当我尝试在 AuthScreen 中点唱时:

when(val response = authViewModel.signInState.value) {
    is Response.Loading -> CircularProgressIndicator()
    is Response.Success -> {
        if (response.data) {
            navController.navigate("profile")
            Log.d(TAG, "Success")
        }
    }
    is Response.Error -> Log.d(TAG, response.message)
}

日志语句打印“成功”,但不会导航到下一个 ProfileScreen。 如何解决这个问题?

您可以从setContent中删除 if-else 。 相反,将ProfileScreen作为主目的地,在其中您可以检查用户是否已通过身份验证。 如果不是,请导航到AuthScreen

@Composable
fun ProfileScreen(navController: NavController) {
    LaunchedEffect(Unit) {
        if(!viewModel.isUserAuthenticated) {
            navController.navigate("auth")
        }
    }
}

如果用户可以从此屏幕注销(即 auth state 可以更改),则代替Unit使用viewModel.isUserAuthenticated作为LaunchedEffect的键(假设isUserAuthenticatedState

如果有人正在寻找,这里有一个更详细的代码和演示答案


代码

ComposeNavigationActivity.kt

class ComposeNavigationActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {Navigation()}
    }
}

可组合物

@Composable
fun MainScreen(navController: NavController) {
    var inputFieldText by remember { mutableStateOf("") }
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Red),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        TextField(
            value = inputFieldText,
            onValueChange = {
                inputFieldText = it
            },
            modifier = Modifier.fillMaxWidth().padding(30.dp)
        )
        Spacer(modifier = Modifier.height(20.dp))
        Button(
            modifier = Modifier.padding(5.dp),
            onClick = {
                navController.navigate(Screen.DetailScreen.withArgs(inputFieldText))
            }) {
            Text(
                text = "Navigate",
                color = Color.White,
                textAlign = TextAlign.Center,
                fontSize = 20.sp
            )
        }
    }
}

@Composable
fun DetailScreen(name: String?) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Green),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        name?.let {
            Text(
                text = it,
                color = Color.White,
                textAlign = TextAlign.Center,
                fontSize = 30.sp
            )
        }
    }
}

A 密封 class 跟踪路线

sealed class Screen(val route:String){
    object MainScreen : Screen(route = "main_screen")
    object DetailScreen : Screen(route = "detail_screen")


    fun withArgs(vararg args:String) : String {
        return buildString {
            append(route)
            args.forEach { arg ->
                append("/$arg")
            }
        }
    }
}

导航

@Composable
fun Navigation() {
    val navController = rememberNavController()
    NavHost(navController = navController, startDestination = Screen.MainScreen.route) {
        composable(route = Screen.MainScreen.route) {
            MainScreen(navController = navController)
        }
        composable(
            route = Screen.DetailScreen.route + "/{name}",
            arguments = listOf(
                navArgument("name") {
                    type = NavType.StringType
                    defaultValue = "Some Default"
                    nullable = true
                }
            )
        ) { entry ->
            DetailScreen(name = entry.arguments?.getString("name"))
        }
    }
}

Output

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM