android - TopAppBar 与 Navigation 集成的脚手架

标签 android kotlin android-jetpack-navigation android-jetpack-compose

如何在 TopAppBar 中显示导航图标(后退箭头或菜单)使用 Scaffold基于 NavController 中的实际位置?我正在使用 Navigating with Compose 1.0.0-alpha02 .下面是一个示例代码,其中描述了它应该如何工作

@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 can only be called from within the same library group (groupId=androidx.navigation) .
第二个问题,如果我想更改 TopAppBar文本我是否必须提升此文本并为每个“屏幕”提供更改此文本的可能性,或者是否有任何简单的内置方法可以像标准 View 系统中那样执行此操作?

最佳答案

感谢 Abdelilah El Aissaoui我知道如何使用 Scaffold只是改变bodyContent .在这种方法中,我们不必通过 navController对于任何 body 元素,一切都在可组合的基础 App 中完成。下面是可以在两个主体之间导航的代码(类(class) -> 学生)
应用:

@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
            )
        }
    )
}
应用正文
@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 中,我使用此模式进行导航:
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
}
因此,当我想导航到下一个 fragment 时,我只需设置 _navigateToStudents.value = true

关于android - TopAppBar 与 Navigation 集成的脚手架,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65079798/

相关文章:

kotlin - 使用 `to`创建 `Pair`是否可以接受?

java - 无法使用发布 apk 中的 Firebase Auth 登录(无 Google Play)

android - 清除 Android 导航组件中的返回堆栈

android - 使用 firebase-messaging 库时使用 firebase-core 库的 Firebase 警告

android - 在 Car Dock 上打开应用程序?

android - 调试器在调用外部 Intent (相机)时断开连接

android - 奥托和 Volley 在方向

android - Android Google Map Marker圈子(多个叠加层没有累积不透明度)

kotlin - 在Android jetpack compose 中,如何在登录时移动屏幕?

Android导航组件+登录流程+嵌套BottomNavigationView