Android Compose 显示底部对话框 (ModalBottomSheet),实现类似BottomSheetDialog的效果

1. ModalBottomSheet

ModalBottomSheetCompose官方的底部对话框,类似传统View中的BottomSheetDialog,可以实现从底部弹出,并支持滑动关闭的效果。

需要注意的是,这里使用的是material3,然后ModalBottomSheet这个组件目前还是实验性的,未来可能会改变或删除。

kotlin 复制代码
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyModalBottomSheetTest1() {
    val sheetState = rememberModalBottomSheetState()
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    if (showBottomSheet) {
        ModalBottomSheet(
            onDismissRequest = {
                showBottomSheet = false
            },
            sheetState = sheetState
        ) {
            // Sheet content
            Column(Modifier.height(300.dp)) {
                Button(onClick = {
                    scope.launch { sheetState.hide() }.invokeOnCompletion {
                        if (!sheetState.isVisible) {
                            showBottomSheet = false
                        }
                    }
                }) {
                    Text("Hide bottom sheet")
                }
            }
        }
    }

    Button(onClick = {
        showBottomSheet = true
    }, Modifier.padding(50.dp)) {
        Text("show")
    }
}

效果如下

2. 自定义圆角大小

通过定义ModalBottomSheetshape可以修改圆角的大小

kotlin 复制代码
shape = RoundedCornerShape(topStart = 3.dp, topEnd = 3.dp)

完整代码如下

kotlin 复制代码
//修改圆角
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyModalBottomSheetTest2() {
    val sheetState = rememberModalBottomSheetState()
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    if (showBottomSheet) {
        ModalBottomSheet(
            shape = RoundedCornerShape(topStart = 3.dp, topEnd = 3.dp),
            onDismissRequest = {
                showBottomSheet = false
            },
            sheetState = sheetState
        ) {
            // Sheet content
            Column(Modifier.height(300.dp)) {
                Button(onClick = {
                    scope.launch { sheetState.hide() }.invokeOnCompletion {
                        if (!sheetState.isVisible) {
                            showBottomSheet = false
                        }
                    }
                }) {
                    Text("Hide bottom sheet")
                }
            }
        }
    }

    Button(onClick = {
        showBottomSheet = true
    }, Modifier.padding(50.dp)) {
        Text("show")
    }
}

效果如下

3. 去除拖动条

对话框顶部的拖动条,我们可能不需要,可以将其去除。

通过定义ModalBottomSheetdragHandle可以去除拖动条。

kotlin 复制代码
dragHandle = {}

完整代码如下

kotlin 复制代码
//去除拖动条
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyModalBottomSheetTest3() {
    val sheetState = rememberModalBottomSheetState()
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    if (showBottomSheet) {
        ModalBottomSheet(
            dragHandle = {},
            onDismissRequest = {
                showBottomSheet = false
            },
            sheetState = sheetState
        ) {
            // Sheet content
            Column(Modifier.height(300.dp)) {
                Button(onClick = {
                    scope.launch { sheetState.hide() }.invokeOnCompletion {
                        if (!sheetState.isVisible) {
                            showBottomSheet = false
                        }
                    }
                }) {
                    Text("Hide bottom sheet")
                }
            }
        }
    }

    Button(onClick = {
        showBottomSheet = true
    }, Modifier.padding(50.dp)) {
        Text("show")
    }
}

效果如下

4. 默认半屏,滑动变成全屏

这里我们把Column的高度改为800.dp,运行程序,对话框默认以半屏显示,向上滑动对话框,可以发现,对话框会变为全屏。

kotlin 复制代码
//半屏展开
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyModalBottomSheetTest4() {
    val sheetState = rememberModalBottomSheetState(
        skipPartiallyExpanded = false,
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    if (showBottomSheet) {
        ModalBottomSheet(
            onDismissRequest = {
                showBottomSheet = false
            },
            sheetState = sheetState
        ) {
            // Sheet content
            Column(Modifier.height(800.dp)) {
                Button(onClick = {
                    scope.launch { sheetState.hide() }.invokeOnCompletion {
                        if (!sheetState.isVisible) {
                            showBottomSheet = false
                        }
                    }
                }) {
                    Text("Hide bottom sheet")
                }
            }
        }
    }

    Button(onClick = {
        showBottomSheet = true
    }, Modifier.padding(50.dp)) {
        Text("show")
    }
}

效果如下所示

5. 默认全屏

skipPartiallyExpanded修改为true,打开对话框的时候,会立即以全屏展示,向下滑动回收的时候,也会跳过半屏阶段。

kotlin 复制代码
//全屏展开
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyModalBottomSheetTest5() {
    val sheetState = rememberModalBottomSheetState(
        skipPartiallyExpanded = true,
    )
    val scope = rememberCoroutineScope()
    var showBottomSheet by remember { mutableStateOf(false) }

    if (showBottomSheet) {
        ModalBottomSheet(
            onDismissRequest = {
                showBottomSheet = false
            },
            sheetState = sheetState
        ) {
            // Sheet content
            Column(Modifier.height(800.dp)) {
                Button(onClick = {
                    scope.launch { sheetState.hide() }.invokeOnCompletion {
                        if (!sheetState.isVisible) {
                            showBottomSheet = false
                        }
                    }
                }) {
                    Text("Hide bottom sheet")
                }
            }
        }
    }

    Button(onClick = {
        showBottomSheet = true
    }, Modifier.padding(50.dp)) {
        Text("show")
    }
}

效果如下所示

6. 返回键不隐藏弹框

将properties中的shouldDismissOnBackPress设置为false,返回键将不会关闭弹框。

kotlin 复制代码
properties = ModalBottomSheetProperties(shouldDismissOnBackPress = false)

7. 修改对话框的主体颜色

containerColor可以修改对话框的主体颜色,如果弹出的弹框底部横条颜色和对话框背景颜色不一样,可以通过修改containerColor来达到颜色一直的效果。

8. 更多ModalBottomSheet的使用

更多ModalBottomSheet的使用详见 : Android Developers | 底部动作条

9.其他三方的Compose底部对话框库

9.1 bottomsheetdialog-compose

Github地址 : workspace/bottomsheetdialog-compose

Jetpack Compose BottomSheetDialog 库,允许您像使用 Dialog 的界面一样使用BottomsheetDialog。此外,它还支持在 BottomSheetDialog 显示时设置导航栏颜色。

这个看一下它的源码,可以发现内部调用的BottomSheetDialogWrapper,而BottomSheetDialogWrapper继承自com.google.android.material.bottomsheet.BottomSheetDialog,也就是说,bottomsheetdialog-compose这个库实质上是封装了传统View中的BottomSheetDialog,来提供给Compose使用。

kotlin 复制代码
private class BottomSheetDialogWrapper(
    private var onDismissRequest: () -> Unit,
    private var properties: BottomSheetDialogProperties,
    private val composeView: View,
    layoutDirection: LayoutDirection,
    density: Density,
    dialogId: UUID
) : BottomSheetDialog(
    ContextThemeWrapper(
        composeView.context,
        if (properties.enableEdgeToEdge) {
            R.style.TransparentEdgeToEdgeEnabledBottomSheetTheme
        } else {
            R.style.TransparentEdgeToEdgeDisabledBottomSheetTheme
        }
    )
)
9.2 FlexibleBottomSheet

Github地址 : skydoves/FlexibleBottomSheet

FlexibleBottomSheet 是一种高级的 Compose Multiplatform 底部工作表,用于分段大小调整、非模态类型,并允许在底部工作表后面进行交互,类似于 Google Maps。它还提供了其他便利,包括指定工作表大小、监视工作表状态和更多自定义。

相关推荐
Kapaseker5 小时前
你不看会后悔的2025年终总结
android·kotlin
alexhilton8 小时前
务实的模块化:连接模块(wiring modules)的妙用
android·kotlin·android jetpack
航Hang*9 小时前
Photoshop 图形与图像处理技术——第8章:图像的色彩与色彩调整和图像的输出与优化
图像处理·笔记·ui·photoshop
聪明努力的积极向上9 小时前
【C#】线程解析:从“页面未响应”到彻底理解 .NET 中的 UI 线程、Task、Thread、COM 与消息泵
ui·.net
ji_shuke9 小时前
opencv-mobile 和 ncnn-android 环境配置
android·前端·javascript·人工智能·opencv
sunnyday042611 小时前
Spring Boot 项目中使用 Dynamic Datasource 实现多数据源管理
android·spring boot·后端
幽络源小助理12 小时前
下载安装AndroidStudio配置Gradle运行第一个kotlin程序
android·开发语言·kotlin
inBuilder低代码平台12 小时前
浅谈安卓Webview从初级到高级应用
android·java·webview
豌豆学姐12 小时前
Sora2 短剧视频创作中如何保持人物一致性?角色创建接口教程
android·java·aigc·php·音视频·uniapp
白熊小北极13 小时前
Android Jetpack Compose折叠屏感知与适配
android