Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)

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

基本使用

效果:
Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)

代码:

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再看下效果

效果:

Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)

代码:

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

自定义样式

去掉小横条

想要实现自定义的下拉样式,然后,不希望要这个小横条(如下图所示),要如何实现呢?
Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)

可以通过dragHandle属性来实现,如下代码

ModalBottomSheet( 	onDismissRequest = { openBottomSheet = false }, 	sheetState = bottomSheetState, 	dragHandle = {} //设置为空 ) { 	 } 

效果如下:
Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)

顶头区自定义按钮

这个dragHandle实际就是顶头那篇区域,如果想要自定义一个取消和确定,也可以实现,如下效果和代码

效果:

Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)

代码:

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) 

意思是,如果你的内容满全屏了,则直接跳过半屏模式,直接展示全屏,效果如下图展示

Jetpack Compose学习(16)——ModalBottomSheet(底部弹窗)

那我内容元素总高度不满全屏高度,又该如何呢?

那更简单,直接将你的内容容器用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") 		} 	} } 

参考

发表评论

评论已关闭。

相关文章