一、概念
Scafford 在 material 包下可以设置 drawerContent,在 material3 包下已经没有。
PermanentNavigationDrawer | 抽屉栏永久显示,占用屏幕。 |
ModalNavigationDrawer | 抽屉栏打开时覆盖在屏幕上。 |
DismissibleNavigationDrawer | 抽屉栏打开会连带把屏幕也向右移动。 |
二、使用
@Composable fun ModalNavigationDrawer( drawerContent: @Composable () -> Unit, //抽屉内容 modifier: Modifier = Modifier, drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed), //控制打开关闭 gesturesEnabled: Boolean = true, //是否响应手势在屏幕上滑动来打开关闭 scrimColor: Color = DrawerDefaults.scrimColor, content: @Composable () -> Unit //屏幕内容 ) |
@Composable material3 提供的 Item 组件,一般不会用它,都是用自定义的。 |
val drawerState = rememberDrawerState(DrawerValue.Closed)
var selectedItemIndex by remember { mutableStateOf(0) } //当前选中的索引(不需要做条目按钮状态可忽略)
ModalNavigationDrawer(
drawerState = drawerState,
//仅在抽屉打开时可以滑动关闭(不会失去外部点击关闭),屏蔽滑动打开,避免滑动冲突
gesturesEnabled = drawerState.isOpen,
//抽屉内容
drawerContent = {
Drawer(
selectedItemIndex = selectedItemIndex,
onSelectedIndexChange = { selectedItemIndex = it },
closeDrawer = {
//延迟抽屉关闭,先等Navigation切换时加载一下,效果更好
coroutineScope.launch {
delay(500)
drawerState.close()
}
}
)
}
) {
//屏幕内容
}
@Composable
private fun Drawer(
selectedItemIndex: Int,
onSelectedIndexChange: (Int) -> Unit,
closeDrawer: () -> Unit,
) {
...
dataList.forEachIndex { item, index ->
DrawerItem(
isSelected = index == selectedItemIndex ,
onClick = {
onSelectedIndexChange(index)
closeDrawer()
}
)
}
}
//抽屉条目
@Composable
private fun DrawerItem(
title: String,
@DrawableRes pic: Int,
isSelected: Boolean, //不需要做条目按钮状态可忽略
onClick: () -> Unit
) {...}