脚手架与 TopAppBar 与导航集成 [英] Scaffold with TopAppBar integration with Navigation
问题描述
如何根据 NavController 中的实际位置使用 Scaffold
在 TopAppBar
中显示导航图标(BackArrow 或 Menu)?我正在使用 使用 Compose 1.0.0-alpha02 导航.下面是一个示例代码,描述了它应该如何工作
How to show navigation icon (BackArrow or Menu) in TopAppBar
using Scaffold
based on actual position in NavController? I am using Navigating with Compose 1.0.0-alpha02. Below is a sample code with a description of how it should work
@Composable
fun App()
{
val navController = rememberNavController()
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = "App title") },
navigationIcon = {
/*
Check if navController back stack has more
than one element. If so show BackButton.
Clicking on that button will move back
*/
val canMoveBack = true
if (canMoveBack)
{
IconButton(onClick = {
// Move back
navController.popBackStack()
}) {
Icon(asset = Icons.Outlined.ArrowBack)
}
}
else
{
IconButton(onClick = {
// show NavDrawer
}) {
Icon(asset = Icons.Outlined.Menu)
}
}
},
)
},
bodyContent = {
AppBody(navController)
}
)
}
我想过类似 navController.backStack.size
之类的东西,但出现错误 NavController.getBackStack 只能从同一个库组 (groupId=androidx.navigation) 中调用
.
I thought about something like navController.backStack.size
but I got error NavController.getBackStack can only be called from within the same library group (groupId=androidx.navigation)
.
第二个问题,如果我想改变 TopAppBar
文本,我是否必须提升这个文本并给每个屏幕"是否可以更改此文本,或者是否有任何简单的内置方法可以像在标准视图系统中那样执行此操作?
And the second question, if I wanted to change the TopAppBar
text do I have to hoist this text and give every "screen" possibility to change this text, or is there any easy built-in way to do this like in the standard View System?
推荐答案
感谢 Abdelilah El Aissaoui我已经知道如何使用一个 Scaffold
并且只更改 bodyContent
.在这个方法中,我们不必将 navController
传递给任何 body 元素,一切都在基础 App 可组合中完成.下面是可以在两个主体之间导航的代码(课程 -> 学生)
Thanks to Abdelilah El Aissaoui I have got an idea of how to do it with one Scaffold
and just changing bodyContent
. In this method, we don't have to pass navController
to any body element, everything is done in base App composable. Below is code which enables to navigate between two bodies (Lesson -> Student)
应用:
@Composable
fun App(
viewModel: MainViewModel
)
{
val navController = rememberNavController()
val baseTitle = "" // stringResource(id = R.string.app_name)
val (title, setTitle) = remember { mutableStateOf(baseTitle) }
val (canPop, setCanPop) = remember { mutableStateOf(false) }
val scaffoldState: ScaffoldState = rememberScaffoldState()
navController.addOnDestinationChangedListener { controller, _, _ ->
setCanPop(controller.previousBackStackEntry != null)
}
// check navigation state and navigate
if (viewModel.navigateToStudents.value)
{
navController.navigate(route = STUDENT_SCREEN_ROUTE)
viewModel.studentsNavigated()
}
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = title) },
navigationIcon = {
if (canPop)
{
IconButton(onClick = {
navController.popBackStack()
}) {
Icon(asset = Icons.Outlined.ArrowBack)
}
}
else
{
IconButton(onClick = {
scaffoldState.drawerState.open()
}) {
Icon(asset = Icons.Outlined.Menu)
}
}
},
)
},
scaffoldState = scaffoldState,
drawerContent = {
DrawerContent()
},
bodyContent = {
AppBody(
viewModel = viewModel,
navController = navController,
setTitle = setTitle
)
}
)
}
AppBody
@Composable
fun AppBody(
viewModel: MainViewModel,
navController: NavHostController,
setTitle: (String) -> Unit,
)
{
NavHost(
navController,
startDestination = LESSON_SCREEN_ROUTE
) {
composable(route = LESSON_SCREEN_ROUTE) {
LessonBody(
viewModel = viewModel,
setTitle = setTitle
)
}
composable(
route = STUDENT_SCREEN_ROUTE
) {
StudentBody(
viewModel = viewModel,
setTitle = setTitle
)
}
}
}
在 ViewModel 中,我使用此模式进行导航:
In the ViewModel I use this pattern to navigate:
private val _navigateToStudents: MutableState<Boolean> = mutableStateOf(false)
val navigateToStudents: State<Boolean> = _navigateToStudents
fun studentsNavigated()
{
// here we can add any logic after doing navigation
_navigateToStudents.value = false
}
所以当我想导航到下一个片段时,我只需设置 _navigateToStudents.value = true
So when I want to navigate to the next fragment I just set _navigateToStudents.value = true
这篇关于脚手架与 TopAppBar 与导航集成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!