阅读 475

Jetpack Compose 的Dialog,Popup,DropdownMenu,DropdownMenuItem用法讲解

这篇文章会介绍Dialog,AlertDialog,Popup,DropdownMenu,DropdownMenuItem的使用

一: Dialog

对话框,一起来看看代码。

@Composable
fun Dialog(
    onDismissRequest: () -> Unit,
    properties: DialogProperties = DialogProperties(),
    content: @Composable () -> Unit
) {...}
复制代码
  • onDismissRequest 当用户尝试关闭对话框时会执行的回调。比如点击返回键,点击对话框以外的区域
  • properties 实现是DialogProperties具体看看DialogProperties的代码
    @Immutable
    class DialogProperties(
      val dismissOnBackPress: Boolean = true,
      val dismissOnClickOutside: Boolean = true,
      val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit
    ){...}
    复制代码
    • dismissOnBackPress 是否可以通过按返回键按钮取消对话框,如果为true,则点击返回键会调用onDismissRequest
    • dismissOnClickOutside 是否可以通过点击对话框以外的区域取消对话框,如果为true,点击对话框区域外会回调onDismissRequest
    • securePolicy 用于在对话框窗口上设置WindowManager.LayoutParams.FLAG。有三种取值SecureFlagPolicy.Inherit,SecureFlagPolicy.SecureOn,SecureFlagPolicy.SecureOff.
  • content 内容

举例:正常的展示标题,内容,还有一个取消,一个确认按钮的对话框。

@Preview
@Composable
fun dialogTest(){
    val state = remember {
        mutableStateOf(true)
    }
    Dialog(
        onDismissRequest = {
            Log.e("ccm","====onDismiss=====")
            state.value = false
        },
        properties = DialogProperties(dismissOnBackPress=true,dismissOnClickOutside = true,securePolicy = SecureFlagPolicy.SecureOff)
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .wrapContentHeight()
                .padding(horizontal = 15.dp)
                .background(
                    Color.White, shape = RoundedCornerShape(8.dp)
                )
        ){
            Spacer(modifier = Modifier.height(10.dp))
            Text(text = "对话框标题",color = Color.Black,fontSize = 16.sp,modifier = Modifier.padding(start = 10.dp),fontWeight = FontWeight.Bold)
            Spacer(modifier = Modifier.height(6.dp))
            Text(text = "对话框内容,对话框内容,对话框内容,对话框内容,对话框内容,对话框内容",modifier = Modifier.padding(horizontal = 10.dp),lineHeight = 20.sp,fontSize = 14.sp)
            Spacer(modifier = Modifier.height(10.dp))
            Divider(modifier = Modifier.height(0.5.dp))
            Row() {
                Button(
                    onClick = {
                        state.value = false
                    },
                    modifier = Modifier.weight(1f,true),
                    shape = RoundedCornerShape(bottomStart = 8.dp),
                    colors = ButtonDefaults.buttonColors(backgroundColor = Color.White),
                ) {
                    Text(text = "取消")
                }
                Button(
                    onClick = {
                        state.value = false
                    },
                    modifier = Modifier.weight(1f,true),
                    shape = RoundedCornerShape(bottomEnd = 8.dp),
                    colors = ButtonDefaults.buttonColors(backgroundColor = Color.White),
                ) {
                    Text(text = "确定")
                }
            }
        }
    }
}
复制代码

Screenshot_20210512_133307_dialog.jpg

二: AlertDialog

AlertDialog对话框,AlertDialog其实是在Dialog的基础上做的一层封装。一起来看看代码。

@Composable
fun AlertDialog(
    onDismissRequest: () -> Unit,
    buttons: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    title: (@Composable () -> Unit)? = null,
    text: @Composable (() -> Unit)? = null,
    shape: Shape = MaterialTheme.shapes.medium,
    backgroundColor: Color = MaterialTheme.colors.surface,
    contentColor: Color = contentColorFor(backgroundColor),
    properties: DialogProperties = DialogProperties()
){
    
    Dialog(
        onDismissRequest = onDismissRequest,
        properties = properties
    ) {
        AlertDialogContent(
            buttons = buttons,
            modifier = modifier,
            title = title,
            text = text,
            shape = shape,
            backgroundColor = backgroundColor,
            contentColor = contentColor
        )
    }
}
复制代码
  • onDismissRequest 当用户尝试关闭对话框时会执行的回调。比如点击返回键,点击对话框以外的区域
  • buttons 按钮区域的显示的内容。可以自己定义
  • modifier 修饰符(以前的文章讲过Modifier用法详解
  • title 标题区域显示的内容
  • text 内容区域显示的内容
  • shape 对话框的形状
  • backgroundColor 对话框的背景颜色
  • contentColor 对话框内容的颜色
  • properties DialogProperties跟上面Dialog一致

举例:

@Preview
@Composable
fun alertDialogTest(){
    AlertDialog(
        onDismissRequest = { },
        buttons = {
            Row() {
                Button(
                    onClick = {
                    },
                    modifier = Modifier.weight(1f,true),
                    shape = RoundedCornerShape(bottomStart = 8.dp),
                    colors = ButtonDefaults.buttonColors(backgroundColor = Color.White),
                ) {
                    Text(text = "取消")
                }
                Button(
                    onClick = {
                    },
                    modifier = Modifier.weight(1f,true),
                    shape = RoundedCornerShape(bottomEnd = 8.dp),
                    colors = ButtonDefaults.buttonColors(backgroundColor = Color.White),
                ) {
                    Text(text = "确定")
                }
            }
        },
        title = {
            Text(text = "对话框标题")
        },
        text = {
            Text(text = "对话框内容对话框内容")
        },
        shape = RoundedCornerShape(8.dp),
        backgroundColor = Color.White,
        contentColor = Color.Black,
        properties = DialogProperties()
    )
}
复制代码

Screenshot_20210512_133255_alertdialog.jpg

三: DropdownMenuItem

DropdownMenuItem就类似我们以前Popupwindow的内容项。具体先来看看代码

@Composable
fun DropdownMenuItem(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    contentPadding: PaddingValues = MenuDefaults.DropdownMenuItemContentPadding,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    content: @Composable RowScope.() -> Unit
)
复制代码
  • onClick 点击事件回调
  • modifier 修饰符
  • enabled 是否可用
  • contentPadding 内容的边距
  • interactionSource 以前讲Button的时候讲过,Button讲解 。可以处理状态的,比如按下的时候什么效果,正常时候什么效果。类似之前再布局文件里写Selector。 比如我们下面的例子中设置,如果是选中时候边框线的颜色是绿色,没有选中时候是黑色。 interactionSource.collectIsPressedAsState() 判断是否按下状态interactionSource.collectIsFocusedAsState() 判断是否获取焦点的状态interactionSource.collectIsDraggedAsState() 判断是否拖动
  • content 具体包含的内容

举个例子,比如我们以前View系统时候经常有这么种场景,点击某个按钮,弹出来Popupwindow,而Popupwindow里面的每一项是一个图标跟文本。而我们用DropdownMenuItem来实现这个图标跟文本,按下和获取焦点的时候是红色的,默认是黑色。

@Composable
fun dropdownMenuItemTest(state:MutableState<Boolean>,icon: ImageVector,text:String){
    val interactionSource = remember { MutableInteractionSource() }
    val pressState = interactionSource.collectIsPressedAsState()
    val focusState = interactionSource.collectIsFocusedAsState()
    DropdownMenuItem(
        onClick = {
            state.value = false
        },
        enabled = true,
        interactionSource = interactionSource
    ) {
        Icon(imageVector = icon, contentDescription = text,tint = if(pressState.value || focusState.value) Color.Red else Color.Black)
        Text(text = text,modifier = Modifier.padding(start = 10.dp),color = if(pressState.value || focusState.value) Color.Red else Color.Black)
    }
}
复制代码

四: DropdownMenu

这个就相当于以前的Popupwindow的效果。上面我们介绍了DropdownMenuItem。现在来看看DropdownMenu。DropdownMenuItem就是DropdownMenu的子项。具体看看代码

@Suppress("ModifierParameter")
@Composable
fun DropdownMenu(
    expanded: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    offset: DpOffset = DpOffset(0.dp, 0.dp),
    properties: PopupProperties = PopupProperties(focusable = true),
    content: @Composable ColumnScope.() -> Unit
){
   ...
        Popup(
            onDismissRequest = onDismissRequest,
            popupPositionProvider = popupPositionProvider,
            properties = properties
        ) {
            DropdownMenuContent(
                expandedStates = expandedStates,
                transformOriginState = transformOriginState,
                modifier = modifier,
                content = content
            )
        }
   ...
}
复制代码
  • expanded 是否展开
  • onDismissRequest 点击DropdownMenu以外的区域会回调该函数。去做隐藏DropdownMenu的逻辑
  • modifier 修饰符
  • offset 是偏移。DpOffset(x,y) x是水平方向上的偏移,y是竖直方向上的偏移
  • properties 是PopupProperties属性。具体来看看代码
    @Immutable
    class PopupProperties(
      val focusable: Boolean = false,
      val dismissOnBackPress: Boolean = true,
      val dismissOnClickOutside: Boolean = true,
      val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit
    ) 
    复制代码
    • focusable 弹出窗口是否可聚焦。如果为true,弹出窗口将接收输入法事件和按键。比如按下返回键,只有focusable为true的时候,才能接收到按下返回键的处理。
    • dismissOnBackPress 弹出按钮是否可以按下后退按钮。如果为true,则按后退按钮将调用onDismissRequest。请注意,focusable必须设置为true才能接收按键事件,如back按钮-如果弹出窗口不可聚焦,则此属性不执行任何操作
    • dismissOnClickOutside 是否可以通过单击弹出窗口的边界之外来取消弹出窗口。如果为true,则在弹出窗口外单击将调用onDismissRequest
    • securePolicy 用于在弹出窗口上设置WindowManager.LayoutParams.FLAG。三种取值SecureFlagPolicy.Inherit,SecureFlagPolicy.SecureOn,SecureFlagPolicy.SecureOff
  • content 具体内容

举个例子,比如我们以前View系统时候经常有这么种场景,点击某个按钮,弹出来DropdownMenu。跟上面的DropdownMenuItem一起配合使用

@Preview
@Composable
fun dropdownMenuTest(){
    val expandState = remember {
        mutableStateOf(false)
    }
    Column() {
        Button(
            onClick = {
                expandState.value = true
            }) {
            Text(text = "打开 DropdownMenu")
        }
        DropdownMenu(
            expanded = expandState.value,
            onDismissRequest = {
                Log.e("ccm","执行了onDismissRequest")
                expandState.value = false
            },
            offset = DpOffset(10.dp,10.dp),
            properties = PopupProperties()
        ) {
            dropdownMenuItemTest(expandState,Icons.Filled.Favorite,"收藏")
            dropdownMenuItemTest(expandState,Icons.Filled.Edit,"编辑")
            dropdownMenuItemTest(expandState,Icons.Filled.Delete,"删除")
        }
    }
}


@Composable
fun dropdownMenuItemTest(state:MutableState<Boolean>,icon: ImageVector,text:String){
    val interactionSource = remember { MutableInteractionSource() }
    val pressState = interactionSource.collectIsPressedAsState()
    val focusState = interactionSource.collectIsFocusedAsState()
    DropdownMenuItem(
        onClick = {
            state.value = false
        },
        enabled = true,
        interactionSource = interactionSource
    ) {
        Icon(imageVector = icon, contentDescription = text,tint = if(pressState.value || focusState.value) Color.Red else Color.Black)
        Text(text = text,modifier = Modifier.padding(start = 10.dp),color = if(pressState.value || focusState.value) Color.Red else Color.Black)
    }
}
复制代码

Screenshot_20210512_132729.jpg

五:Popup

Popup就类似以前的Popupwindow,我们可以看到其实上面的DropdownMenu是Popup的一个具体实现。具体来看看Popup的代码

@Composable
fun Popup(
    alignment: Alignment = Alignment.TopStart,
    offset: IntOffset = IntOffset(0, 0),
    onDismissRequest: (() -> Unit)? = null,
    properties: PopupProperties = PopupProperties(),
    content: @Composable () -> Unit
){...}
复制代码
  • alignment 对齐方式。以前我们将Column时候就讲过
  • offset 偏移。IntOffset(x,y) x是水平方向上的偏移,y是竖直方向上的偏移。
  • onDismissRequest 当用户在弹出窗口外单击时执行的回调
  • properties 跟上面类似
  • content 具体的包含的内容

举例。上面DropdownMenu的例子改成用Popup

@Preview
@Composable
fun popUpTest(){
    val expandState = remember {
        mutableStateOf(false)
    }
    Column() {
        Button(
            onClick = {
                expandState.value = true
            }) {
            Text(text = "打开 DropdownMenu")
        }
        Popup(
            alignment = Alignment.TopStart,
            onDismissRequest = {
                Log.e("ccm","执行了onDismissRequest")
                expandState.value = false
            },
            offset = IntOffset(10,140),
        ) {
            Column(
                modifier = Modifier.width(IntrinsicSize.Min).shadow(
                    elevation = 2.dp,shape = RoundedCornerShape(3.dp)
                ).background(Color.White,shape = RoundedCornerShape(3.dp))
            ) {
                dropdownMenuItemTest(expandState,Icons.Filled.Favorite,"收藏")
                dropdownMenuItemTest(expandState,Icons.Filled.Edit,"编辑")
                dropdownMenuItemTest(expandState,Icons.Filled.Delete,"删除")
            }
        }
    }
}

@Composable
fun dropdownMenuItemTest(state:MutableState<Boolean>,icon: ImageVector,text:String){
    val interactionSource = remember { MutableInteractionSource() }
    val pressState = interactionSource.collectIsPressedAsState()
    val focusState = interactionSource.collectIsFocusedAsState()
    DropdownMenuItem(
        onClick = {
            state.value = false
        },
        enabled = true,
        interactionSource = interactionSource
    ) {
        Icon(imageVector = icon, contentDescription = text,tint = if(pressState.value || focusState.value) Color.Red else Color.Black)
        Text(text = text,modifier = Modifier.padding(start = 10.dp),color = if(pressState.value || focusState.value) Color.Red else Color.Black)
    }
}
复制代码

Screenshot_20210512_132715.jpg

文章分类
Android
文章标签