Compose使用指南-Dialog标准用法

1,371 阅读4分钟

Compose 中怎么写 Dialog?

在 Android 的 Jetpack Compose 框架中,Dialog 是一个常见的 UI 组件,用于向用户展示重要的信息或者提示用户做出决策。Compose 提供了灵活的方式来实现 Dialog,在保证功能性的同时,也极大地简化了 Dialog 的编写流程。本文将从两个角度介绍 Compose 中如何编写 Dialog:首先是标准用法,其次是如何封装一个通用的 Dialog 组件。

一、Compose 中的 Dialog 标准用法

在 Compose 中,Dialog 是一个封闭的容器,显示在屏幕内容之上,阻挡与背景的交互。一般情况下,Dialog 常用于确认、提示或者展示信息给用户。Compose 提供了 Dialog 这个 Composable 函数,可以很轻松地创建一个基础对话框。

1.1 使用 Dialog 创建基础对话框

使用 Compose 的 Dialog,你可以自定义对话框内容,包括标题、正文、按钮等。最基础的使用方式如下:

@Composable
fun BasicDialogExample(showDialog: Boolean, onDismissRequest: () -> Unit) {
    if (showDialog) {
        Dialog(onDismissRequest = { onDismissRequest() }) {
            Surface(
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight(),
                shape = RoundedCornerShape(16.dp),
                color = MaterialTheme.colorScheme.surface
            ) {
                Column(
                    modifier = Modifier.padding(16.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(text = "标题", style = MaterialTheme.typography.h6)
                    Spacer(modifier = Modifier.height(8.dp))
                    Text(text = "这是对话框的内容", style = MaterialTheme.typography.body1)
                    Spacer(modifier = Modifier.height(16.dp))
                    Row(
                        horizontalArrangement = Arrangement.End,
                        modifier = Modifier.fillMaxWidth()
                    ) {
                        TextButton(onClick = { onDismissRequest() }) {
                            Text("取消")
                        }
                        TextButton(onClick = { /* 确认操作逻辑 */ }) {
                            Text("确认")
                        }
                    }
                }
            }
        }
    }
}

1.2 Dialog 关键参数解析

  • onDismissRequest:这个参数是必须的,用于处理当用户点击对话框外部区域或者按下返回键时对话框关闭的逻辑。
  • 内容区域Dialog 不像 Android 传统的 AlertDialog 那样自带布局,你可以在 Dialog 中自由放置任何 Composable,例如 Surface 来控制 Dialog 的形状、背景色等。

这种方式提供了很大的灵活性,可以完全自定义对话框的外观和行为。

二、封装一个通用的 Dialog

在实际开发中,我们经常需要复用对话框来展示不同的消息、确认框或者选择框。为了减少重复代码和增强组件的复用性,我们可以将常用的 Dialog 逻辑封装成一个通用的 Dialog 组件。

2.1 通用 Dialog 组件的封装

我们可以将 Dialog 的常见逻辑提取出来,比如标题、内容、按钮的处理,创建一个通用的 CustomDialog 组件:

@Composable
fun CustomDialog(
    showDialog: Boolean,
    title: String,
    message: String,
    confirmButtonText: String = "确认",
    cancelButtonText: String = "取消",
    onConfirm: () -> Unit,
    onDismiss: () -> Unit
) {
    if (showDialog) {
        Dialog(onDismissRequest = { onDismiss() }) {
            Surface(
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight(),
                shape = RoundedCornerShape(12.dp),
                color = MaterialTheme.colorScheme.surface
            ) {
                Column(
                    modifier = Modifier.padding(16.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(text = title, style = MaterialTheme.typography.h6)
                    Spacer(modifier = Modifier.height(8.dp))
                    Text(text = message, style = MaterialTheme.typography.body1)
                    Spacer(modifier = Modifier.height(16.dp))
                    Row(
                        horizontalArrangement = Arrangement.End,
                        modifier = Modifier.fillMaxWidth()
                    ) {
                        TextButton(onClick = { onDismiss() }) {
                            Text(cancelButtonText)
                        }
                        TextButton(onClick = { 
                            onConfirm()
                            onDismiss() 
                        }) {
                            Text(confirmButtonText)
                        }
                    }
                }
            }
        }
    }
}

2.2 如何使用 CustomDialog

在实际使用时,我们可以轻松调用 CustomDialog,传入需要展示的内容和逻辑:

@Composable
fun DialogUsageExample() {
    var showDialog by remember { mutableStateOf(false) }
    
    Column(modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = { showDialog = true }) {
            Text("显示对话框")
        }

        CustomDialog(
            showDialog = showDialog,
            title = "确认操作",
            message = "你确定要执行这个操作吗?",
            confirmButtonText = "确认",
            cancelButtonText = "取消",
            onConfirm = { /* 确认逻辑 */ },
            onDismiss = { showDialog = false }
        )
    }
}

在这个示例中,CustomDialog 的使用变得非常简单,只需要传入特定参数即可实现自定义 Dialog 的功能。同时可以根据需求调整按钮文本、对话框内容等,极大地提高了代码的复用性和灵活性。

2.3 通用 Dialog 组件的扩展

封装后的 CustomDialog 还可以根据项目需求进一步扩展。比如你可以加入图标、不同类型的按钮,甚至可以将按钮的布局也做成可配置的参数,从而适配不同场景的需求。

@Composable
fun CustomDialog(
    showDialog: Boolean,
    title: String,
    message: String,
    confirmButtonText: String = "确认",
    cancelButtonText: String = "取消",
    icon: @Composable (() -> Unit)? = null,
    onConfirm: () -> Unit,
    onDismiss: () -> Unit
) {
    if (showDialog) {
        Dialog(onDismissRequest = { onDismiss() }) {
            Surface(
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight(),
                shape = RoundedCornerShape(12.dp),
                color = MaterialTheme.colorScheme.surface
            ) {
                Column(
                    modifier = Modifier.padding(16.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    icon?.invoke()
                    Spacer(modifier = Modifier.height(8.dp))
                    Text(text = title, style = MaterialTheme.typography.h6)
                    Spacer(modifier = Modifier.height(8.dp))
                    Text(text = message, style = MaterialTheme.typography.body1)
                    Spacer(modifier = Modifier.height(16.dp))
                    Row(
                        horizontalArrangement = Arrangement.End,
                        modifier = Modifier.fillMaxWidth()
                    ) {
                        TextButton(onClick = { onDismiss() }) {
                            Text(cancelButtonText)
                        }
                        TextButton(onClick = { 
                            onConfirm()
                            onDismiss() 
                        }) {
                            Text(confirmButtonText)
                        }
                    }
                }
            }
        }
    }
}

你可以传入图标组件,甚至对 UI 布局进一步自定义,灵活处理更多复杂场景。

三、总结

Jetpack Compose 让 Dialog 的编写变得更加简洁和灵活,标准的 Dialog 用法可以轻松实现基础的对话框功能,而通过封装,我们可以创建通用的 Dialog 组件,方便在项目中复用和扩展。希望本文能够帮助你更好地掌握 Compose 中 Dialog 的编写与封装技巧。