使用 jetpack 撰写导航中的 popBackStack 时如何更改脚手架顶部栏的标题?

nay*_*rde 10 android android-jetpack-compose

我正在将多活动应用程序迁移到单活动应用程序以进行撰写。

我创建了一个可组合的主页,其中包含一个顶部应用程序栏,其标题如下所示:


@Composable
fun Home() {
val navController = rememberNavController()
    var actionBarTitle by rememberSaveable { mutableStateOf("Home") }
    var actionBarSubtitle by rememberSaveable { mutableStateOf("") }
    Scaffold(topBar = {
        Header(title = actionBarTitle, subTitle = actionBarSubtitle,
                onBackPress = { navController.popBackStack() },
            showInfo = true, onActionClick = {
                navController.navigate(Screen.Info.route)
            }, modifier = Modifier.fillMaxWidth())
    }) {
        AppNavigation(navController = navController, onNavigate = { title, subtitle ->
                actionBarTitle = title
                actionBarSubtitle = subtitle
            })
}


Run Code Online (Sandbox Code Playgroud)

每当我对任何屏幕使用 navController.navigate 时,都会触发 onNavigate,如下所示:


onNavigate("Top up", "Please topm up with minimum of X amount")
navController.navigateTo(Screen.TopUp.route)
Run Code Online (Sandbox Code Playgroud)

我的问题是,当我使用 backpress 时,我不知道我将导航到哪个可组合屏幕,所以我如何调用 onNavigate 来更改标题。

ngl*_*ber 7

您可以使用 观察导航变化currentBackstackEntryFlow

@Composable
fun Home() {
    val context = LocalContext.current
    val navController = rememberNavController()
    ...
    LaunchedEffect(navController) {
        navController.currentBackStackEntryFlow.collect { backStackEntry ->
            // You can map the title based on the route using:
            actionBarTitle = getTitleByRoute(context, backStackEntry.destination.route)
        }
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

当然,您需要编写此内容getTitleByRoute()才能根据导航路线获取正确的标题。它会是这样的:

fun getTitleByRoute(context: Context, route:String): String {
    return when (route) {
        "Screen1" -> context.getString(R.string.title_screen_1)
        // other cases
        else -> context.getString(R.string.title_home)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以简单地使用 `context.getString(R.string.yourString)`...检查我编辑的答案... (2认同)

Mon*_*tel 5

1. 在使用 Composable 的同时使用 LiveData 更改屏幕标题

实现“androidx.compose.runtime:runtime-livedata:1.2.0-beta02”

2.创建ViewModel类

class MainViewModel: ViewModel() {
    private var _screenTitle = MutableLiveData("")
    val screenTitle: LiveData<String>
        get() = _screenTitle

    fun setTitle(newTitle: String) {
        _screenTitle.value = newTitle
    }
}
Run Code Online (Sandbox Code Playgroud)

3. 在你的活动课上

setContent {
        Surface(color = MaterialTheme.colors.onPrimary) {
            LoadMainScreen()
        }
    } 
Run Code Online (Sandbox Code Playgroud)

// 观察屏幕标题

@Composable
fun LoadMainScreen(mainViewModel: MainViewModel = viewModel()){

val title: String by mainViewModel.screenTitle.observeAsState("")

 Scaffold(
    topBar = {
        TopAppBar(title = { title?.let { Text(it) } },

          navigationIcon = {
          Icon(
                imageVector = Icons.Default.Menu,
                contentDescription = "Menu",
                tint = Color.White
              )
          }           
        )
      } 
    )
}  
Run Code Online (Sandbox Code Playgroud)

4. 更改屏幕上的标题值

@Composable
fun ScreenOne(mainViewModel: MainViewModel) {
    LaunchedEffect(Unit){
        mainViewModel.setTitle("One")
    }
}
@Composable
fun ScreenTwo(mainViewModel: MainViewModel) {
    LaunchedEffect(Unit){
        mainViewModel.setTitle("Two")
    }
}
Run Code Online (Sandbox Code Playgroud)