Jetpack:020-Jetpack导航示例:底部导航栏

文章目录

  • 1. 概念介绍
  • 2. 使用方法
  • 3. 代码与分析
    • 3.1 示例代码
    • 3.2 代码分析
  • 4. 内容总结

我们在上一章回中介绍了Jetpack中导航相关的内容,本章回中主要介绍 导航的综合示例:底部导航栏。闲话休提,让我们一起Talk Android Jetpack吧!

1. 概念介绍

我们在前面章回中介绍过底部导航栏的知识,如果有看官忘记的话可以点击这里查看之前的文章,本章回在此基础上添加导航功能。也就是说点击不同的底部导航标签切换到不同的页面。

回想一下,我们在使用Fragment和Activity实现底部导航时的做法:创建一个Activity并且在Activity中包含Fragment容器,通过Fragment容器来切换Fragment,进而实现底部导航功能。大家看完本章回的内容后就回来对比一下哪种方式的导航方便一些。

2. 使用方法

创建底部导航的方法和在compose中使用Navigation库实现导航的方法类似,下面是详细的使用步骤:

  • 创建NavController;
  • 创建NavHost,并且把各个页面添加到容器中;
  • 通过NavController的navigate方法实现各个页面之间的导航;

3. 代码与分析

3.1 示例代码

介绍完创建底部导航的方法后,我们通过具体的示例代码来演示:

fun ExScaffold(
) {

    //这个NavController主要用来切换底部的导航,只能在这里获取,不能在底部导航的方法中获取,不会导航栏会出现在屏幕上方
    val  naviController = rememberNavController()

    Scaffold(
        modifier = Modifier.background(color = MaterialTheme.colorScheme.primary),
        topBar = { CustomCenterAppBar()},

        bottomBar = { BottomNaviBarTemplate(navController = naviController)},

        //控制FAB的位置,只有两种
        floatingActionButtonPosition = FabPosition.End,
        floatingActionButton = { CustomFAB(snackbarHostState, scope) },
    ) {innerPadding->
        Column(modifier = Modifier
            .padding(innerPadding)
            .fillMaxSize()
            .background(color = CusColor)
        ) {
            Text(text = "hello")
        }

        //这个是自定义的页面配合自定义的底部导航栏使用:CustomBottomNavigationBar
        //这个navHost容器是配合BottomNaviBarTemplate使用的,可以当作代码模板
        NavHost(
            navController = naviController,
            startDestination = BottomNaviScreen.HomeScreen.route,
            modifier = Modifier.padding(innerPadding),
        ) {
            composable(BottomNaviScreen.PersonScreen.route) { PersonScreen(naviController)}
            composable(BottomNaviScreen.HomeScreen.route) { HomeScreen(naviController) }
            composable(BottomNaviScreen.SettingScreen.route) { SettingScreen(naviController) }
        }
    }
}

//参考官方文档编写,compose中习惯把页面叫screen,而在Flutter中习惯叫page,因此在代码中screen和page的含义相同
sealed class BottomNaviScreen(val route:String, val resourceId:Int,val icon:ImageVector) {
    object PersonScreen : BottomNaviScreen("person", R.string.navi_person,Icons.Default.Person)
    object HomeScreen : BottomNaviScreen("home",R.string.navi_home,Icons.Default.Home)
    object SettingScreen: BottomNaviScreen("setting",R.string.navi_setting,Icons.Default.Settings)
}

//创建底部导航栏的模板代码
@Composable
fun BottomNaviBarTemplate(navController: NavController) {
    val screens = listOf(
        BottomNaviScreen.PersonScreen,
        BottomNaviScreen.HomeScreen,
        BottomNaviScreen.SettingScreen,
    )

    NavigationBar(
        containerColor = Color.Blue,
        contentColor = Color.Green, //这个颜色不起作用
    ) {
        val navBackStackEntry by navController.currentBackStackEntryAsState()
        val currentDestination = navBackStackEntry?.destination

        screens.forEach { item ->
            NavigationBarItem(
                icon = { Icon(imageVector = item.icon, contentDescription = null)},
                label = { Text(text = stringResource(id = item.resourceId))},
                selected = currentDestination?.hierarchy?.any{it.route == item.route} == true,
                onClick = {
                    navController.navigate(item.route) {
                        //popup to the start destination of the graph to avoid building up a large
                        //stack of destinations on the back stack as users select items.
                        popUpTo(navController.graph.startDestinationId) {
                            saveState = true
                        }
                        // avoid multiple copies of the same destination when reselecting the same item
                        launchSingleTop = true
                        //restore state when reselecting a previously selected item
                        restoreState = true
                    }
                },
                //设置bar的各种颜色
                colors = NavigationBarItemDefaults.colors(
                    selectedIconColor = Color.Cyan,
                    selectedTextColor = Color.Cyan,
                    //这个颜色最好和NavigationBar的containerColor颜色保持一致,不然会在Icon外层显示一个背景颜色
                    indicatorColor = Color.Blue,
                    unselectedIconColor = Color.Yellow,
                    unselectedTextColor = Color.Yellow,
                ),
            )
        }
    }
}

3.2 代码分析

我们在上面的代码中添加了注释,这样方便大家理解代码,不过还有细节还需要说明:底部导航是通过Scaffold可组合函数实现的,Scaffold函数提供了槽位,我们只需要把底部导航放到槽位中就可以,同时导航容器也要放到放到Scaffold中,也就是说NavHost容器中包含所有的导航页面,需要放在Scaffold函数中,不能放在底部导航的函数中,不然导航栏会出现在屏幕上方,大家可以自己动手去试试。本示例参考了官方文档,大家可以点击这里查看官方文档中的内容。

下面是程序的运行结果,不过图片是静态的,没有导航切换效果。
Jetpack:020-Jetpack导航示例:底部导航栏_第1张图片

4. 内容总结

最后,我们对本章回的内容做一个全面的总结:

  • 底部导航栏的用来和普通导航的用法类似,包含三个步骤;
  • 底部导航栏位于Scaffold中,导航容器也需要放到Scaffold中;
  • 使用Navigation实现底部导航栏比使用Fragment实现导航更加方便一些;

看官们,与Jetpack中底部导航栏相关的内容就介绍到这里,欢迎大家在评论区交流与讨论!

你可能感兴趣的:(一起Talk,AndroidJetPack吧,移动开发,Jetpack,compose,脚手架scaffold,底部导航栏)