Jetpack Compose组件ModalDrawer

675 阅读2分钟

ModalDrawer是Jetpack Compose提供的侧滑抽屉组件,它展开后位于应用程序的大部分UI之上。 抽屉始终由抽屉外部的启示组件打开,例如顶部应用栏中的导航菜单图标。 抽屉可以通过以下方式关闭: 1 选择了抽屉中的一个子项 2 点击屏幕空白 3 手势向起始侧边滑动

来看一下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,
    //界面布局,收起抽屉后展示的UI
    content: @Composable () -> Unit
): Unit

先来看一下demo的界面:

在这里插入图片描述

抽屉侧滑部分的布局: 包括一个头部和三个Item

/**
 * 抽屉的布局
 */
@Composable
private fun DrawerContent(
    modifier: Modifier = Modifier,
    currenItemFlag:MutableState<DrawerItemFlag>,
    closeDrawer: () -> Unit
){
    Column(modifier = modifier.fillMaxSize()) {
        DrawerHeader()
        DrawerItem(
            painter = painterResource(id = R.drawable.ic_baseline_lens_24),
            label = stringResource(id = R.string.one),
            isSelected = if(currenItemFlag.value == DrawerItemFlag.One) true else false,
            onClick = {
                closeDrawer()
                currenItemFlag.value = DrawerItemFlag.One
            }
        )
        DrawerItem(
            painter = painterResource(id = R.drawable.ic_baseline_lens_24),
            label = stringResource(id = R.string.two),
            isSelected = if(currenItemFlag.value == DrawerItemFlag.Two) true else false,
            onClick = {
                closeDrawer()
                currenItemFlag.value = DrawerItemFlag.Two
            }
        )
        DrawerItem(
            painter = painterResource(id = R.drawable.ic_baseline_lens_24),
            label = stringResource(id = R.string.three),
            isSelected = if(currenItemFlag.value == DrawerItemFlag.Three) true else false,
            onClick = {
                closeDrawer()
                currenItemFlag.value = DrawerItemFlag.Three
            }
        )
    }
}

抽屉头部布局: 一个简单的头像和文本标签布局

/**
 * 抽屉布局中的头部布局
 */
@Composable
private fun DrawerHeader(
    modifier: Modifier = Modifier
) {
    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
        modifier = modifier
            .fillMaxWidth()
            .background(Color.Blue)
            .height(dimensionResource(id = R.dimen.header_height))
            .padding(dimensionResource(id = R.dimen.header_padding))
    ) {
        Image(
            painter = painterResource(id = R.drawable.ic_baseline_account_circle_24),
            contentDescription =
            stringResource(id = R.string.me),
            modifier = Modifier.size(100.dp)
        )
        Text(
            text = stringResource(id = R.string.me),
            color = MaterialTheme.colors.surface
        )
    }
}

抽屉Item布局:

/**
 * 抽屉的Item
 */
@Composable
private fun DrawerItem(
    modifier: Modifier = Modifier,
    label:String,
    painter: Painter,
    tintColor:Color = Color.DarkGray,
    isSelected:Boolean = false,
    onClick:() -> Unit
){
    val color = if(isSelected) Color.Blue else tintColor
    Row(
        horizontalArrangement = Arrangement.Start,
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxWidth()
            .height(80.dp)
            .padding(10.dp)
            .clickable { onClick() }
    ) {
        Icon(
            painter = painter,
            contentDescription = null, // decorative
            tint = color

        )
        Spacer(Modifier.width(16.dp))
        Text(
            text = label,
            style = MaterialTheme.typography.body2,
            color = color
        )
    }
}

完整的抽屉布局:

@OptIn(ExperimentalUnitApi::class)
@Composable
fun ModalDrawerDemo(drawerState: DrawerState) {

    val scope = rememberCoroutineScope()
    //当前抽屉被选中的Item
    val currenItemFlag = remember {
        mutableStateOf(DrawerItemFlag.One)
    }
    ModalDrawer(
        drawerState = drawerState,
        drawerShape = MaterialTheme.shapes.small,
        drawerContent = {
              DrawerContent(currenItemFlag = currenItemFlag) {
                  scope.launch { drawerState.close() }
              }
        },
        content = {
            //根据选择的draweritem切换不同的content
            if(currenItemFlag.value == DrawerItemFlag.One) {
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(Color.Red)
                        .padding(16.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(text = stringResource(id = R.string.one), fontSize = TextUnit(50f,
                        TextUnitType.Sp))
                }
            }else if (currenItemFlag.value == DrawerItemFlag.Two){
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .background(Color.Green)
                        .padding(16.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(text = stringResource(id = R.string.two), fontSize = TextUnit(50f,
                        TextUnitType.Sp))
                }
            }else{
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(16.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(text = stringResource(id = R.string.three), fontSize = TextUnit(50f,
                        TextUnitType.Sp))
                }
            }
        }
    )
}