原文地址: 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")
} }
}
}
}

这里需要注意的是:

  1. 展示弹窗,实际和Dialog类似,也是控制一个Boolean数值变化从而弹出
  2. 关闭弹窗的代码得用上面的写法,否则就是没有下滑效果!!(之前就是在这踩坑了,虽然没人关注这点哈哈)

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")
}
}
}

参考

Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)的更多相关文章

  1. Jetpack Compose学习(7)——MD样式架构组件Scaffold及导航底部菜单

    Jetpack Compose学习(7)--MD样式架构组件Scaffold及导航底部菜单 | Stars-One的杂货小窝 Compose给我们提供了一个Material Design样式的首页组件 ...

  2. Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用

    原文地址: Jetpack Compose学习(3)--图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝 本篇分别对常用的组件:图标(Ic ...

  3. Jetpack Compose学习(5)——从登录页美化开始学习布局组件使用

    原文:Jetpack Compose学习(5)--从登录页美化开始学习布局组件使用 | Stars-One的杂货小窝 本篇主要讲解常用的布局,会与原生Android的布局控件进行对比说明,请确保了解A ...

  4. Jetpack Compose学习(6)——关于Modifier的妙用

    原文: Jetpack Compose学习(6)--关于Modifier的妙用 | Stars-One的杂货小窝 之前学习记录中也是陆陆续续地将常用的Modifier的方法穿插进去了,本期就来详细的讲 ...

  5. Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用

    原文地址 Jetpack Compose学习(4)--Image(图片)使用及Coil图片异步加载库使用 | Stars-One的杂货小窝 本篇讲解下关于Image的使用及使用Coil开源库异步加载网 ...

  6. Jetpack Compose学习(9)——Compose中的列表控件(LazyRow和LazyColumn)

    原文:Jetpack Compose学习(9)--Compose中的列表控件(LazyRow和LazyColumn) - Stars-One的杂货小窝 经过前面的学习,大致上已掌握了compose的基 ...

  7. Jetpack Compose学习(11)——Navigation页面导航的使用

    原文:Jetpack Compose学习(11)--Navigation页面导航的使用 - Stars-One的杂货小窝 在Android原生的View开发中的,也是有Navigation,原生我之后 ...

  8. Jetpack Compose学习(1)——从登录页开始入门

    原文地址:Jetpack Compose学习(1)--从登录页开始入门 | Stars-One的杂货小窝 Jetpack Compose UI在前几天出了1.0正式版,之前一直还在观望,终于是出了正式 ...

  9. Jetpack Compose学习(2)——文本(Text)的使用

    原文: Jetpack Compose学习(2)--文本(Text)的使用 | Stars-One的杂货小窝 对于开发来说,文字最为基础的组件,我们先从这两个使用开始吧 本篇涉及到Kotlin和DSL ...

  10. Jetpack Compose学习(8)——State及remeber

    原文地址: Jetpack Compose学习(8)--State状态及remeber关键字 - Stars-One的杂货小窝 之前我们使用TextField,使用到了两个关键字remember和mu ...

随机推荐

  1. 解决get请求特殊字符问题

    @Bean public ServletWebServerFactory webServerFactory() { TomcatServletWebServerFactory fa = new Tom ...

  2. Canon LBP2900安装Linux驱动的方法

    Canon LBP2900使用Linux CAPT驱动,其最新版本是2017年3月的v2.71版,可从佳能中国官网下载.由于驱动包不提供install.sh安装脚本,某些依赖库需要检查后手动安装,具体 ...

  3. 个人对Debian桌面系统的简单使用分享

    前言 自从安装Debian12作为双系统已经过了大半个月,平常主用Debian,偶尔切回Windows找找文档,总体来说体验还是很不错的.先贴个桌面照 为什么要使用Linux作为个人桌面 当初刚从Wi ...

  4. java基础之“获取系统类型,区分Windows和Linux系统”

    一.获取系统类型,区分Windows和Linux系统 // 判断是否是windows系统 System.getProperties().getProperty("os.name") ...

  5. 一款基于 .NET 开源、可以拦截并修改 WinSock 封包的 Windows 软件

    前言 今天大姚给大家分享一款基于 .NET 开源(MIT license).可以拦截并修改 WinSock 封包的 Windows 软件:WinsockPacketEditor. 工具介绍 Winso ...

  6. java从小白到老白⑤——传智播客27版笔记

    今天主要说些内部类的相关基础知识,如果能做出下面这个小题目,再下面的内容不看也罢(面试题答案在最后) 内部类面试题:补全下列代码,实现目标输出,其中描述阶段的数字只能调用已有变量,不能用其他方式 pu ...

  7. maven安装教程(亲测有用)

    先去https://maven.apache.org/download.cgi下第二个: 自己下不下来的,微信搜我公众号[勾玉技术]发送关键字[maven]获取百度云链接下载. 解压到任意文件夹,记得 ...

  8. 测试使用自己编译的WPF框架(本地nuget 包引用)

    上一篇博客 本地编译WPF框架源码 - wuty007 - 博客园 说到自己在本地编译WPF 框架源码,并在本地 源码 的 \wpf\artifacts\packages\Debug\NonShipp ...

  9. 卡掉hash的方法

    大质数hash 通常,这个质数会选择在 \(10^9\) 附近,如 \(998244353\),\(10^9+7\). 考虑生日碰撞,欲达到 50% 成功率,需要尝试的次数为 \[\begin{ali ...

  10. Go中的map和指针

    本文参考:https://www.liwenzhou.com/posts/Go/08_map/ MAP(映射) Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现.(类似于Pyth ...