android BottomSheet及AlertDialog的几种material3 常见ui的用法
1、运行效果
2、测试代码
package com.example.android.architecture.blueprints.todoapp.utilimport android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheetDemoApp() {MaterialTheme {Surface(modifier = Modifier.fillMaxSize()) {BottomSheetDemoScreen()}}
}@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheetDemoScreen() {// ModalBottomSheet 状态var showModalSheet by remember { mutableStateOf(false) }val confirmStateChange: (SheetValue) -> Boolean = { newValue ->// 只有当新的状态不是展开状态时,才允许状态变更newValue != SheetValue.Expanded}val modalSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false,confirmValueChange = confirmStateChange)val scope = rememberCoroutineScope()// BottomSheetScaffold 状态val scaffoldState = rememberBottomSheetScaffoldState()// 自定义 BottomSheet 状态var showCustomSheet by remember { mutableStateOf(false) }// DropdownMenu 状态var showDropdown by remember { mutableStateOf(false) }// AlertDialog 状态var showAlertDialog by remember { mutableStateOf(false) }// 使用 BottomSheetScaffold 作为基础布局BottomSheetScaffold(scaffoldState = scaffoldState,sheetContent = {Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {Text(text = "BottomSheetScaffold 示例",fontSize = 18.sp,fontWeight = FontWeight.Bold,modifier = Modifier.padding(bottom = 8.dp))Text(text = "这是一个持久化底部弹窗,可通过拖拽调整高度。",fontSize = 14.sp,color = Color.Gray)}},sheetPeekHeight = 56.dp,sheetShape = MaterialTheme.shapes.extraLarge,) {Column(modifier = Modifier.fillMaxSize().padding(16.dp),horizontalAlignment = Alignment.CenterHorizontally) {Text(text = "底部弹出框组件演示",fontSize = 24.sp,fontWeight = FontWeight.Bold,modifier = Modifier.padding(vertical = 24.dp),textAlign = TextAlign.Center)// 1. ModalBottomSheet 按钮Button(onClick = { showModalSheet = true },modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)) {Text("1. 显示 ModalBottomSheet")}// 2. BottomSheetScaffold 已在布局中// 3. 自定义 BottomSheet 按钮Button(onClick = { showCustomSheet = true },modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)) {Text("2. 显示 自定义 BottomSheet")}// 4. DropdownMenu 按钮Box(modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)) {Button(onClick = { showDropdown = true },modifier = Modifier.fillMaxWidth()) {Text("3. 显示 DropdownMenu")}DropdownMenu(expanded = showDropdown,onDismissRequest = { showDropdown = false },modifier = Modifier.fillMaxWidth()) {DropdownMenuItem(text = { Text("下拉菜单项 1") },onClick = { showDropdown = false })DropdownMenuItem(text = { Text("下拉菜单项 2") },onClick = { showDropdown = false })}}// 5. AlertDialog 按钮Button(onClick = { showAlertDialog = true },modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)) {Text("4. 显示 AlertDialog")}}}// 1. ModalBottomSheetif (showModalSheet) {ModalBottomSheet(sheetState = modalSheetState,onDismissRequest = {scope.launch {modalSheetState.hide()}.invokeOnCompletion {if (!modalSheetState.isVisible) {showModalSheet = false}}},content = {Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {Text(text = "ModalBottomSheet 示例",fontSize = 18.sp,fontWeight = FontWeight.Bold,modifier = Modifier.padding(bottom = 8.dp))Text(text = "这是一个模态底部弹窗,点击外部区域或按下返回键可关闭。",fontSize = 14.sp,color = Color.Gray,modifier = Modifier.padding(bottom = 16.dp))Button(onClick = {scope.launch {modalSheetState.hide()}.invokeOnCompletion {if (!modalSheetState.isVisible) {showModalSheet = false}}},modifier = Modifier.fillMaxWidth()) {Text("关闭")}}})}// 3. 自定义 BottomSheetBox(modifier = Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.3f)), // 可选:添加遮罩背景contentAlignment = Alignment.BottomCenter // 🔥 关键点:控制子组件居中底部显示) {AnimatedVisibility(visible = showCustomSheet,enter = slideInVertically(initialOffsetY = { it }),exit = slideOutVertically(targetOffsetY = { it })) {Box(modifier = Modifier.fillMaxWidth().height(600.dp).background(MaterialTheme.colorScheme.surface)) {Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {Text(text = "自定义 BottomSheet 示例",fontSize = 18.sp,fontWeight = FontWeight.Bold,modifier = Modifier.padding(bottom = 8.dp))Text(text = "这是一个使用 AnimatedVisibility 实现的自定义底部弹窗。",fontSize = 14.sp,color = Color.Gray,modifier = Modifier.padding(bottom = 16.dp))Button(onClick = { showCustomSheet = false },modifier = Modifier.fillMaxWidth()) {Text("关闭")}}}}}// 4. AlertDialogif (showAlertDialog) {AlertDialog(onDismissRequest = { showAlertDialog = false },title = {Text(text = "AlertDialog",fontSize = 18.sp,fontWeight = FontWeight.Bold)},text = {Text(text = "这是一个通过自定义布局显示的对话框。",fontSize = 14.sp,color = Color.Gray)},confirmButton = {TextButton(onClick = { showAlertDialog = false }) {Text("确认")}},dismissButton = {TextButton(onClick = { showAlertDialog = false }) {Text("取消")}},modifier = Modifier.fillMaxWidth().wrapContentHeight(),shape = MaterialTheme.shapes.extraLarge)}
}@Preview(showBackground = true)
@Composable
fun BottomSheetDemoPreview() {BottomSheetDemoApp()
}
3、代码说明
包含多种底部弹出框(Bottom Sheet)和对话框的Compose界面:
BottomSheetScaffold:作为主布局,展示可拖拽展开的持久化底部面板;
ModalBottomSheet:显示模态底部弹窗,点击外部或返回键可关闭;
自定义 BottomSheet:使用 AnimatedVisibility 实现带动画的底部弹出层;
DropdownMenu:实现下拉菜单,供用户选择操作项;
AlertDialog:展示标准的确认对话框。
4、代码详细描述
4.1. Jetpack Compose
Android 的现代 UI 工具包,采用声明式方式构建界面。
使用 Kotlin 编写,简化了 UI 开发流程,无需操作 XML 布局文件。
核心组件包括 @Composable 函数、状态管理(如 mutableStateOf、remember)、组合式 UI 构建等。
4.2. Material Design 3 (M3) 组件
使用 androidx.compose.material3 包中的组件,遵循 Material Design 3 规范。
关键组件:
BottomSheetScaffold: 提供一个可拖拽展开的底部面板,作为主布局的一部分。
ModalBottomSheet: 显示模态底部弹窗,点击外部或返回键可关闭。
AlertDialog: 显示标准确认对话框。
DropdownMenu: 实现下拉菜单,常用于选择项。
Button, Text, Box, Column, Surface, MaterialTheme: 基础 UI 组件和容器。
注意:@OptIn(ExperimentalMaterial3Api::class) 表示部分 API 处于实验阶段,可能在未来版本中变更。
4.3. 状态管理
使用 var showModalSheet by remember { mutableStateOf(false) } 管理组件的状态(显示/隐藏)。
remember 用于保存 Composable 生命周期内的状态。
mutableStateOf 将变量包装为可观察状态,当值变化时触发 UI 重绘。
4.4. 协程(Coroutines)与异步交互
使用 kotlinx.coroutines.launch 启动协程来执行非阻塞操作(例如隐藏 ModalBottomSheet)。
invokeOnCompletion 用于监听协程完成事件,更新 UI 状态。
4.5. 自定义 BottomSheet 实现
使用 AnimatedVisibility 结合 slideInVertically 和 slideOutVertically 实现带有滑动动画的自定义底部弹窗。
使用 Box 容器 + contentAlignment = Alignment.BottomCenter 控制弹窗的位置居中底部。
可添加遮罩背景 Color.Black.copy(alpha = 0.3f) 来提升视觉焦点。
4.6. 动画
Jetpack Compose 动画库 (androidx.compose.animation) 提供丰富的动画能力:
AnimatedVisibility:控制组件的显示/隐藏动画。
slideInVertically / slideOutVertically:垂直方向上的进入和退出动画。
4.7. UI 预览(Preview)
使用 @Preview 注解在 Android Studio 中实时预览 Composable 函数。
BottomSheetDemoPreview() 调用 BottomSheetDemoApp() 以可视化整个应用界面。
4.8. 样式与主题
使用 MaterialTheme 应用全局主题样式,包括颜色、字体、形状等。
自定义文本大小 (fontSize)、权重 (fontWeight)、对齐 (textAlign)、内边距 (padding) 等属性增强 UI 展示效果。