原文地址: Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)-Stars-One的杂货小窝
接手新公司项目里,有代码用到了这个弹窗,由于需要重构架构和进行相关统一组件封装,顺手学习下这个组件,发现还是踩了些坑(怪我以Compose里的Dialog来用了哈哈)
介绍
这个组件是属于M3里的组件,需要引入androidx.compose.material3这个依赖
不过新版本的Android Studio创建项目都是直接通过Bom引入了,是都会带有了这个依赖了(这里就不过多提及加入依赖了)
PS:主要是现在新版本Android Studio,新创建的项目,依赖分了几个文件,贴的话会很麻烦,见谅哈哈
- androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
复制代码 基本使用
效果:
代码:- 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再看下效果
效果:
代码:- 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}")
- }
- }
- }
- }
复制代码 自定义样式
去掉小横条
想要实现自定义的下拉样式,然后,不希望要这个小横条(如下图所示),要如何实现呢?
可以通过dragHandle属性来实现,如下代码- ModalBottomSheet(
- onDismissRequest = { openBottomSheet = false },
- sheetState = bottomSheetState,
- dragHandle = {} //设置为空
- ) {
-
- }
复制代码 效果如下:
顶头区自定义按钮
这个dragHandle实际就是顶头那篇区域,如果想要自定义一个取消和确定,也可以实现,如下效果和代码
效果:
代码:- 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)
复制代码 意思是,如果你的内容满全屏了,则直接跳过半屏模式,直接展示全屏,效果如下图展示
那我内容元素总高度不满全屏高度,又该如何呢?
那更简单,直接将你的内容容器用Modifier设置为全屏即可- ModalBottomSheet(
- onDismissRequest = { openBottomSheet = false },
- sheetState = bottomSheetState,
- ) {
- //直接填充满屏即可!
- Column(modifier= Modifier.fillMaxSize()) {
- 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")
- }
- }
- }
复制代码 参考
- Bottom sheets | Jetpack Compose | Android Developers
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |