android 在jetpack编写导航中使用popBackStack时如何更改scaffold顶部栏的标题?

dy2hfwbg  于 2022-12-25  发布在  Android
关注(0)|答案(3)|浏览(207)

我正在将我的多活动应用程序迁移到单活动应用程序进行合成。
我创建了一个可组合的Home,其中包含一个Top应用程序栏,标题如下所示:

@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
            })
}

每当我使用navController时,onNavigate就会被触发。导航到任何屏幕,如下所示:

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

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

8e2ybdfx

8e2ybdfx1#

您可以使用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)
        }
    }
    ...
}

当然,您需要编写这个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)
    }
}
kcrjzv8t

kcrjzv8t2#

1.使用组合时使用LiveData更改屏幕标题

实现“androidx.compose.runtime:运行时间-实时数据:1.2.0-beta 02”

2.创建视图模型类

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

    fun setTitle(newTitle: String) {
        _screenTitle.value = newTitle
    }
}

3.在活动课上

setContent {
        Surface(color = MaterialTheme.colors.onPrimary) {
            LoadMainScreen()
        }
    }

//观察屏幕标题

@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
              )
          }           
        )
      } 
    )
}

4.从屏幕更改标题值

@Composable
fun ScreenOne(mainViewModel: MainViewModel) {
    LaunchedEffect(Unit){
        mainViewModel.setTitle("One")
    }
}
@Composable
fun ScreenTwo(mainViewModel: MainViewModel) {
    LaunchedEffect(Unit){
        mainViewModel.setTitle("Two")
    }
}
kmpatx3s

kmpatx3s3#

可以从navHostcontrollor中获取当前目的地的标签,将其作为标题即可

val navController = rememberNavController()
    val currentBackStackEntry by navController.currentBackStackEntryAsState()
    val title = currentBackStackEntry?.destination?.label

缺省composable函数的实现方式如下

/**
 * Add the [Composable] to the [NavGraphBuilder]
 *
 * @param route route for the destination
 * @param arguments list of arguments to associate with destination
 * @param deepLinks list of deep links to associate with the destinations
 * @param content composable for the destination
 */
public fun NavGraphBuilder.composable(
    route: String,
    arguments: List<NamedNavArgument> = emptyList(),
    deepLinks: List<NavDeepLink> = emptyList(),
    content: @Composable (NavBackStackEntry) -> Unit
) {
    addDestination(
        ComposeNavigator.Destination(provider[ComposeNavigator::class], content).apply {
            this.route = route
            arguments.forEach { (argumentName, argument) ->
                addArgument(argumentName, argument)
            }
            deepLinks.forEach { deepLink ->
                addDeepLink(deepLink)
            }
        }
    )
}

过载:

fun NavGraphBuilder.composable(
    route: String,
    label: String,
    arguments: List<NamedNavArgument> = emptyList(),
    deepLinks: List<NavDeepLink> = emptyList(),
    content: @Composable (NavBackStackEntry) -> Unit
) {
    addDestination(
        ComposeNavigator.Destination(provider[ComposeNavigator::class], content).apply {
            this.route = route
            this.label = label
            arguments.forEach { (argumentName, argument) ->
                addArgument(argumentName, argument)
            }
            deepLinks.forEach { deepLink ->
                addDeepLink(deepLink)
            }
        }
    )
}

您可以按以下方式使用它:

composable("route", "title") {
        ...
      }

相关问题