抽屉布局ModalDrawer的使用
@Composable
fun ModalDrawer(
drawerContent: @Composable ColumnScope.() -> Unit,
modifier: Modifier = Modifier,
drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
gesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerDefaults.Elevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
scrimColor: Color = DrawerDefaults.scrimColor,
content: @Composable () -> Unit
) {
}
注意点:
- ModalDrawer 放在根布局(如果不需要沉浸式可以不用放在根布局)
- 如果需要使用标题栏,标题栏可以放到content中
- 样式中需要使用
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
代码如下
@Composable
fun Drawer2Screen() {
val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
val list = listOf(
DrawerItemData(
0,
R.string.title_robot,
R.drawable.ic_home_24,
R.drawable.ic_home_select_24
),
DrawerItemData(
1,
R.string.title_map,
R.drawable.ic_widgets_24,
R.drawable.ic_widgets_select_24
)
)
val context = LocalContext.current
ModalDrawer(
drawerState = drawerState,
drawerContent = {
DrawerHeader {
scope.launch { drawerState.close() }
}
DrawerContent(modifier = Modifier.fillMaxSize(), lists = list) {
Toast.makeText(context, "点击了${it}", Toast.LENGTH_SHORT).show()
scope.launch { drawerState.close() }
}
},
content = {
Scaffold(
modifier = Modifier.systemBarsPadding(),
topBar = {
IconButton(onClick = { scope.launch { drawerState.open() } }) {
Icon(
painter = painterResource(id = R.drawable.ic_home_select_24),
contentDescription = "打开抽屉",
tint = MaterialTheme.colors.primary
)
}
},
) {
Spacer(Modifier.height(20.dp))
Button(onClick = { scope.launch { drawerState.open() } }) {
Text("Click to open")
}
}
}
)
}
抽屉头部布局:DrawerHeader
@Composable
fun DrawerHeader(action: (int: Int) -> Unit) {
ConstraintLayout(
modifier = Modifier
.fillMaxWidth()
) {
val (top_view, iv_header, tv_name, tv_version) = createRefs()
val bgImg = LocalContext.current.getDrawable(R.drawable.side_nav_bar)
Box(modifier = Modifier
.constrainAs(top_view) {
start.linkTo(parent.start)
top.linkTo(parent.top)
}
.fillMaxWidth()
.height(210.dp)
.drawBehind {
bgImg?.apply {
updateBounds(0, 0, size.width.toInt(), size.height.toInt())
draw(drawContext.canvas.nativeCanvas)
}
}
)
Image(
painter = painterResource(id = R.drawable.ic_robot),
contentDescription = null,
modifier = Modifier
.systemBarsPadding(
start = false,
top = true,
end = false,
bottom = false
)
.constrainAs(iv_header) {
start.linkTo(top_view.start, margin = 16.dp)
top.linkTo(top_view.top, margin = 24.dp)
}
.clickable { action(1) }
.size(120.dp, 80.dp)
)
Text(
text = stringResource(id = R.string.app_name), modifier = Modifier
.constrainAs(tv_name) {
start.linkTo(iv_header.start)
top.linkTo(iv_header.bottom, margin = 8.dp)
},
style = TextStyle(
fontSize = 16.sp,
textAlign = TextAlign.Start,
color = Color.White
)
)
Text(
text = String.format("V%s",BuildConfig.VERSION_NAME),
modifier = Modifier
.constrainAs(tv_version) {
start.linkTo(tv_name.start)
top.linkTo(tv_name.bottom, margin = 8.dp)
},
style = TextStyle(
fontSize = 16.sp,
textAlign = TextAlign.Start,
color = Color.White
)
)
}
}
抽屉列表布局:
@Composable
fun DrawerContent(modifier: Modifier, lists: List<DrawerItemData>, onClick: (id: Int) -> Unit) {
val selectId = remember { mutableStateOf(lists[0].id) }
LazyColumn(modifier = modifier, contentPadding = PaddingValues(4.dp, 6.dp)) {
itemsIndexed(lists, key = { _, item -> item.id }) { index, item ->
DrawerContentItem(itemData = item, selectId = selectId.value) {
if (selectId.value != it) selectId.value = it
onClick(index)
}
Spacer(modifier = Modifier.height(6.dp))
}
}
}
抽屉条目布局:
@Composable
fun DrawerContentItem(itemData: DrawerItemData, selectId: Int, onClick: (id: Int) -> Unit) {
val isSelect = itemData.id == selectId
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.height(36.dp)
.clickable { onClick(itemData.id) }
.background(
if (isSelect) MaterialTheme.colors.primary else Color.Transparent,
RoundedCornerShape(4.dp)
),
) {
Spacer(modifier = Modifier.width(10.dp))
Image(
painter = painterResource(id = if (isSelect) itemData.imgSelect else itemData.img),
contentDescription = null
)
Spacer(modifier = Modifier.width(10.dp))
Text(
text = stringResource(id = itemData.rs),
style = TextStyle(
fontSize = 16.sp,
textAlign = TextAlign.Start,
color = if (isSelect) MaterialTheme.colors.primaryVariant else Color.Black
)
)
}
}
条目使用数据结构:
data class DrawerItemData(
val id: Int,
@StringRes val rs: Int,
@DrawableRes val img: Int,
@DrawableRes val imgSelect: Int,
)