本篇大约有5564个字,阅读预计需要6.96分钟
合集 - Android Jetpack Compose(17) 1. Jetpack Compose学习(1)——从登录页开始入门 2021-08-11 2. Jetpack Compose学习(2)——文本(Text)的使用 2021-08-22 3. Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用 2021-09-08 4. Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用 2021-09-15 5. Jetpack Compose学习(5)——从登录页美化开始学习布局组件使用 2021-09-25 6. Jetpack Compose学习(6)——关于Modifier的妙用 2021-10-03 7. Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单 2021-10-04 8. Jetpack Compose学习(8)——State及remeber 2022-07-30 9. Jetpack Compose学习(9)——Compose中的列表控件(LazyRow和LazyColumn) 2022-08-11 10. Jetpack Compose学习(10)——使用Compose物料清单BOM,更好管理依赖版本 2023-02-16 11. Jetpack Compose学习(11)——Navigation页面导航的使用 2023-02-25 12. Jetpack Compose学习(12)——Material Theme的主题色切换 2024-07-26 13. Jetpack Compose学习(13)——Compose生命周期及副作用函数 2024-08-15 14. Jetpack Compose学习(14)——ConstraintLayout约束布局使用 2024-12-05 15. Jetpack Compose学习(15)——Pager组件的使用(对标ViewPager) 2024-12-18 16. Compose里Navigation导航的优雅跳转 04-24 17. Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗) 07-11 收起 原文地址: Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)-Stars-One的杂货小窝
接手新公司项目里,有代码用到了这个弹窗,由于需要重构架构和进行相关统一组件封装,顺手学习下这个组件,发现还是踩了些坑(怪我以Compose里的Dialog来用了哈哈)
介绍 这个组件是属于M3里的组件,需要引入androidx.compose.material3这个依赖
不过新版本的Android Studio创建项目都是直接通过Bom引入了,是都会带有了这个依赖了(这里就不过多提及加入依赖了)
PS:主要是现在新版本Android Studio,新创建的项目,依赖分了几个文件,贴的话会很麻烦,见谅哈哈
androidx-material3 = { group = www.hefeilaws.com/ "androidx.compose.material3", name = "material3" } 基本使用 效果: PixPin_2025-07-11_18-08-42
代码:
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class) @Composable fun ModelSheetDemoPage(modifier: Modifier = Modifier) { val context = LocalContext.current
Column(modifier = Modifier.statusBarsPadding()) {
var openBottomSheet by rememberSaveable { mutableStateOf(false) }
val scope = rememberCoroutineScope()
val bottomSheetState = rememberModalBottomSheetState()
// App content
Column(
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Button(
onClick = { openBottomSheet = !openBottomSheet },
modifier = Modifier.align(Alignment.CenterHorizontally)
) {
Text(text = "Show Bottom Sheet")
}
}
// Sheet content
if (openBottomSheet) {
ModalBottomSheet(
onDismissRequest = { openBottomSheet = false },
sheetState = bottomSheetState,
) {
Text("内容数据")
Button(
// Note: If you provide logic outside of onDismissRequest to remove the sheet,
// you must additionally handle intended state cleanup, if any.
onClick = {
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible) {
openBottomSheet = false
}
}
}
) {
Text("Hide Bottom Sheet")
}
}
}
}
}
这里需要注意的是:
展示弹窗,实际和Dialog类似,也是控制一个Boolean数值变化从而弹出 关闭弹窗的代码得用上面的写法,否则就是没有下滑效果!!(之前就是在这踩坑了,虽然没人关注这点哈哈) PS:后续代码为了保证重点和观感,会有所精简
ModalBottomSheet默认是有半屏和全屏模式的,但上面例子由于我们的内容元素不多,高度不是大,我们改造下,加个LazyColumn再看下效果
效果:
PixPin_2025-07-11_18-17-34
代码:
ModalBottomSheet( onDismissRequest = { openBottomSheet = false }, sheetState = bottomSheetState, ) {
//....
LazyColumn {
items(20) {
Row(modifier= Modifier.fillMaxWidth().height(48.dp).padding(horizontal = 24.dp), verticalAlignment = Alignment.CenterVertically) {
Text("hello ${it}")
}
}
}
} 自定义样式 去掉小横条 想要实现自定义的下拉样式,然后,不希望要这个小横条(如下图所示),要如何实现呢? image
可以通过dragHandle属性来实现,如下代码
ModalBottomSheet( onDismissRequest = { openBottomSheet = false }, sheetState = bottomSheetState, dragHandle = {www.hefeilaws.com/} //设置为空 ) {
} 效果如下: image
顶头区自定义按钮 这个dragHandle实际就是顶头那篇区域,如果想要自定义一个取消和确定,也可以实现,如下效果和代码
效果:
PixPin_2025-07-11_18-36-04
代码:
ModalBottomSheet( onDismissRequest = { openBottomSheet = false }, sheetState = bottomSheetState, dragHandle = { Row(modifier= Modifier.fillMaxWidth().padding(horizontal = 24.dp)) { Text("取消",modifier= Modifier.clickable{ scope .launch { bottomSheetState.hide() } .invokeOnCompletion { if (!bottomSheetState.isVisible) { openBottomSheet = false } } }) Spacer(modifier= Modifier.weight(1f)) Text("确定",modifier= Modifier.clickable{ scope .launch { bottomSheetState.hide() } .invokeOnCompletion { if (!bottomSheetState.isVisible) { openBottomSheet = false } } }) } } ) 禁止展示半屏 如果不想要展示半屏的效果,可以通过下面这样设置
val bottomSheetState = rememberModalBottomSheetState(true) 意思是,如果你的内容满全屏了,则直接跳过半屏模式,直接展示全屏,效果如下图展示
PixPin_2025-07-11_18-42-27
那我内容元素总高度不满全屏高度,又该如何呢?
那更简单,直接将你的内容容器用Modifier设置为全屏即可
ModalBottomSheet( onDismissRequest = { openBottomSheet = false }, sheetState = bottomSheetState, ) {
//直接填充满屏即可!
Column(modifier= Modifier.fillMaxSize()) {
Text("内容数据")
Button(https://www.hefeilaws.com/
// Note: If you provide logic outside of onDismissRequest to remove the sheet,
// you must additionally handle intended state cleanup, if any.
onClick = {
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible) {
openBottomSheet = false
}
}
}
) {
Text("Hide Bottom Sheet")
}
}
}