Jetpack Compose底部状态栏+Fab制作

The Rhine–Meuse–Scheldt river delta in the Netherlands

效果图如上:

控件默认支持一些属性的配置,下面直接上代码,在代码中加注释解释:

注意:需要导入androidx.compose.material包,如果导入material3的包会导致颜色设置、某些设置项异常

@Composable  
fun Greeting2() {  
	// 创建导航
    val navController = rememberNavController()  
    val scaffoldState = rememberScaffoldState()  
    Scaffold(  
	    // 创建底部导航栏,和NavHost结合导航。传入navController进行点击控制。
        bottomBar = { MyBottomBar(navController) },  
        // 新建一个悬浮Fab,用于嵌入
        floatingActionButton = {  
            FloatingActionButton(  
                modifier = Modifier.size(156.dp),  
                onClick = {  
                // FAB onClick  
            },  
                shape = CircleShape) {  
                Icon(imageVector = Icons.Default.Add, contentDescription = "Add", modifier = Modifier.size(100.dp))  
            }  
        },  
  
        scaffoldState = scaffoldState,  
        // Fab是否嵌入底部栏
        isFloatingActionButtonDocked = true,  
        // Fab嵌入底部栏的位置
        floatingActionButtonPosition = FabPosition.Center  
        
    ) { innerPadding ->  
	    // 导航,一共有四个页面,每个页面都是一个Composable
        NavHost(navController, startDestination = MainActivityPages.Profile.route, Modifier.padding(innerPadding)) {  
            composable(MainActivityPages.Profile.route) { Text(text = "aaa") }  
            composable(MainActivityPages.Info.route) { Text(text = "bbb") }  
            composable(MainActivityPages.Message.route) { Text(text = "bbb") }  
            composable(MainActivityPages.My.route) { Text(text = "bbb") }  
        }    }}  
  
@Composable  
fun MyBottomBar(navController: NavHostController) {  
	// 准备导航按钮
    val bottomMenuItemsList = prepareBottomMenu()  
	// 设定导航的样式、嵌入的形状等
    BottomAppBar(backgroundColor = Color.White,  
        cutoutShape = CircleShape,  
        modifier = Modifier.height(180.dp)  
    ) {  
	    // 获取当前导航的内容
        val navBackStackEntry by navController.currentBackStackEntryAsState()  
        val currentDestination = navBackStackEntry?.destination  
        bottomMenuItemsList.forEachIndexed { index, menuItem ->
	        // 一共有四个按钮,Fab居中,所以要在中间创建一个空的按钮占位  
            if (index == 2) {  
                // add an empty space for FAB  
                BottomNavigationItem(  
                    modifier = Modifier.size(156.dp),  
                    selected = false,  
                    onClick = {},  
                    icon = {},  
                    enabled = false  
                )  
            }  
			// 其余按钮正常处理
            BottomNavigationItem(  
	            // 选择的颜色
                selectedContentColor = Color.Red,  
                // 未选择的颜色
                unselectedContentColor = Color.Gray,  
                // 是否一直显示标题,false为选中才显示标题
                alwaysShowLabel = false,  
                modifier = Modifier.size(100.dp),  
                onClick = {  
	                // 点击事件,利用导航
                    navController.navigate(menuItem.route) {  
                        // Pop up 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.findStartDestination().id) {  
                            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  
                    }  
                },  
                label = { Text(menuItem.label, fontSize = 35.sp) },  
                icon = {  
                    Icon(  
                        imageVector = menuItem.icon,  
                        contentDescription = menuItem.label,  
                        modifier = Modifier.size(100.dp),  
                    )  
                },  
                // 利用导航判断当前按钮是否选择
                selected = currentDestination?.hierarchy?.any { it.route == menuItem.route } == true,//(selectedItem == menuItem.route),  
                enabled = true  
            )  
        }  
    }}  
  
private fun prepareBottomMenu(): List<MainActivityPages> {  
    val bottomMenuItemsList = arrayListOf<MainActivityPages>()  
  
    // add menu items  
    bottomMenuItemsList.add(MainActivityPages.Profile)  
    bottomMenuItemsList.add(MainActivityPages.Info)  
    bottomMenuItemsList.add(MainActivityPages.Message)  
    bottomMenuItemsList.add(MainActivityPages.My)  
  
    return bottomMenuItemsList  
}  
  
data class BottomMenuItem(val label: String, val icon: ImageVector, val route: String)  
  
@Preview(showBackground = true)  
@Composable  
fun GreetingPreview2() {  
    HomeOfCarTheme {  
        Greeting2()  
    }  
}