本文展示了 Scaffold 的一个简单的基本用法,更多用法请看官方文档
一、Scaffold 脚手架
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun Scaffold() {
// BottomBar 当前选择项
var selectedItem by remember { mutableStateOf(0) }
// TopBar 下拉菜单打开状态
var dropDownMenuOpen by remember { mutableStateOf(false) }
// Scaffold 状态,可以用来获取侧边栏打开状态
val scaffoldState = rememberScaffoldState()
// 获取组合感知作用域,以便在可组合项外启动协程
val scope = rememberCoroutineScope()
// 设置 BottomBar 项
val items = listOf(
BottomBarItem("首页", Icons.Outlined.Home),
BottomBarItem("消息", Icons.Outlined.Email),
BottomBarItem("我", Icons.Outlined.Face)
)
// 设置 TopBar 下拉菜单选项
val menus = listOf("刷新数据", "设置", "退出")
// 拦截系统返回按键事件
BackHandler(
enabled = scaffoldState.drawerState.isOpen
) {
scope.launch {
scaffoldState.drawerState.close()
}
}
// 脚手架
Scaffold (
topBar = {
TopAppBar (
title = {
Text("首页")
},
navigationIcon = {
IconButton(onClick = {
scaffoldState.drawerState.apply {
scope.launch {
if (isOpen) close() else open()
}
}
}) {
Icon(imageVector = Icons.Filled.Menu, contentDescription = null)
}
},
// 设置 TopBar 右侧按钮
actions = {
IconButton(onClick = {
dropDownMenuOpen = !dropDownMenuOpen
}) {
Icon(imageVector = Icons.Filled.Face, contentDescription = null)
}
// 下拉菜单
Menu(options = menus, expanded = dropDownMenuOpen) {
dropDownMenuOpen = false
}
}
)
},
bottomBar = {
BottomNavigation {
items.forEachIndexed { index, bottomBarItem ->
BottomNavigationItem(
selected = selectedItem == index,
onClick = {
selectedItem = index
},
icon = {
Icon(imageVector = bottomBarItem.icon, null)
},
label = {
Text(bottomBarItem.name)
}
)
}
}
},
// 侧边栏
drawerContent = {
Text(text = "Hello")
},
scaffoldState = scaffoldState
) {
Box (
modifier = Modifier
.fillMaxSize()
// 此处设置 padding 以便偏移顶部栏和底部栏(如果存在的话),否则报错
.padding(it),
contentAlignment = Alignment.Center
) {
when (selectedItem) {
0 -> {
Text("首页")
}
1 -> {
Text("消息")
}
2 -> {
Text("我")
}
}
}
}
}
@ExperimentalMaterialApi
@Composable
fun Menu(
options: List<String>,
expanded: Boolean,
onDismissRequest: () -> Unit
) {
DropdownMenu(
expanded = expanded,
onDismissRequest = onDismissRequest
) {
Column {
options.forEach { option ->
ListItem(text = {
Text(option)
})
}
}
}
}
data class BottomBarItem (val name: String, val icon: ImageVector)