这篇文章会对BottomSheetScaffold,ModalBottomSheetLayout以及BackdropScaffold的使用进行讲解。 我们在前面的文章讲过槽位的控件Scaffold,而今天这几个控件也是典型的槽位控件。
一:BottomSheetScaffold
类似我们之前讲过的Scaffold讲解
先来看看代码
@Composable
@ExperimentalMaterialApi
fun BottomSheetScaffold(
sheetContent: @Composable ColumnScope.() -> Unit,
modifier: Modifier = Modifier,
scaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState(),
topBar: (@Composable () -> Unit)? = null,
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
floatingActionButton: (@Composable () -> Unit)? = null,
floatingActionButtonPosition: FabPosition = FabPosition.End,
sheetGesturesEnabled: Boolean = true,
sheetShape: Shape = MaterialTheme.shapes.large,
sheetElevation: Dp = BottomSheetScaffoldDefaults.SheetElevation,
sheetBackgroundColor: Color = MaterialTheme.colors.surface,
sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
sheetPeekHeight: Dp = BottomSheetScaffoldDefaults.SheetPeekHeight,
drawerContent: @Composable (ColumnScope.() -> Unit)? = null,
drawerGesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerDefaults.Elevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
drawerScrimColor: Color = DrawerDefaults.scrimColor,
backgroundColor: Color = MaterialTheme.colors.background,
contentColor: Color = contentColorFor(backgroundColor),
content: @Composable (PaddingValues) -> Unit
){...}
- sheetContent 底部抽屉的内容
- modifier 修饰符Modifier讲解
- scaffoldState BottomSheetScaffoldState的状态,我们来看看具体可以控制哪几个状态
@ExperimentalMaterialApi @Stable class BottomSheetScaffoldState( val drawerState: DrawerState, val bottomSheetState: BottomSheetState, val snackbarHostState: SnackbarHostState )
- drawerState可以去控制左边抽屉的状态
- bottomSheetState 可以去控制底部抽屉的状态
- snackbarHostState 可以控制Snackbar的状态
- topBar 顶部控件,可用我们之前讲过的TopAppBar TopAppBar讲解
- snackbarHost 其实是设置了一个Snackbar控件 关于Snackbar以及snackbarHost属性,我们在Snackbar,Scaffold讲解该篇文章讲过
- floatingActionButton 浮动的button 我们在各种Button讲解讲过
- floatingActionButtonPosition 设置floatingActionButton的按钮的位置。是在底部居中还是再右下角,有一半会盖在sheetContent上面
- sheetGesturesEnabled 是否能通过手指滑动去打开和关闭底部的抽屉
- sheetShape 底部抽屉的形状
- sheetElevation 底部抽屉的阴影
- sheetBackgroundColor 底部抽屉的背景颜色
- sheetContentColor 底部抽屉的内容颜色
- sheetPeekHeight 是底部抽屉的初始的高度
- drawerContent 左边抽屉的内容 比如我们前面文章讲过ModalDrawer
- drawerGesturesEnabled 是否能通过手指拖动的形式去打开和关闭左边的抽屉
- drawerShape 左边抽屉的形状
- drawerElevation 左边抽屉的阴影
- drawerBackgroundColor 左边抽屉的背景颜色
- drawerContentColor 左边抽屉的内容的颜色
- drawerScrimColor 左边抽屉打开的时候,右边剩余部分的颜色值
- backgroundColor BottomSheetScaffold控件的背景颜色
- contentColor BottomSheetScaffold控件的内容的颜色
- content BottomSheetScaffold控件包含的内容 举例:
@ExperimentalMaterialApi
@Preview()
@Composable
fun bottomSheetScaffoldTest() {
val scaffoldState = rememberBottomSheetScaffoldState()
val scope = rememberCoroutineScope()
BottomSheetScaffold(
sheetContent = {
Spacer(modifier = Modifier.height(10.dp))
Text(text = " sheetContent title")
Text(text = " sheetContent content")
Text(text = " sheetContent content2")
Text(text = " sheetContent content3")
Text(text = " sheetContent content4")
Text(text = " sheetContent content5")
Text(text = " sheetContent content6")
Text(text = " sheetContent content7")
Text(text = " sheetContent content8")
Text(text = " sheetContent content9")
Spacer(modifier = Modifier.height(10.dp))
},
modifier = Modifier.fillMaxWidth(),
scaffoldState = scaffoldState,
topBar = { topBarView(scaffoldState) },
// snackbarHost =
floatingActionButton = {
FloatingActionButton(
onClick = {
scope.launch {
if(scaffoldState.bottomSheetState.isCollapsed){
scaffoldState.bottomSheetState.expand()
}else{
scaffoldState.bottomSheetState.collapse()
}
}
}
){
}
},
floatingActionButtonPosition = FabPosition.Center,
sheetGesturesEnabled = true,
sheetShape = RoundedCornerShape(2.dp),
sheetElevation = 8.dp,
sheetBackgroundColor = Color.Red,
sheetContentColor = Color.White,
sheetPeekHeight = 50.dp,
drawerContent = {
drawView()
},
drawerGesturesEnabled = true,
drawerShape = RoundedCornerShape(4.dp),
drawerElevation = 16.dp,
drawerBackgroundColor = Color.White,
drawerContentColor = Color.Black,
drawerScrimColor = DrawerDefaults.scrimColor,
backgroundColor = Color.White,
contentColor = Color.Black
) {
Spacer(modifier = Modifier.height(10.dp))
Text(text = " BottomSheetScaffold title")
Text(text = " BottomSheetScaffold content")
Button(onClick = {
scope.launch {
scaffoldState.snackbarHostState.showSnackbar("被打开了","隐藏",SnackbarDuration.Short)
}
}) {
Text(text = "打开SnackBar")
}
}
}
@Composable
fun drawView(){
val drawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
ModalDrawer(
drawerContent = {
Text(text = "ModalDrawer Content",modifier = Modifier
.fillMaxWidth()
.height(200.dp))
},
drawerState = drawerState,
gesturesEnabled = true,
drawerShape = MaterialTheme.shapes.large,
drawerElevation = DrawerDefaults.Elevation,
drawerBackgroundColor = Color.Red,
drawerContentColor = Color.White,
scrimColor = DrawerDefaults.scrimColor
) {
Column() {
Text(text = "ModalDrawer Title")
Text(text = "ModalDrawer Content")
Button(onClick = {
scope.launch {
drawerState.open()
}
}) {
Text(text = "打开")
}
}
}
}
@ExperimentalMaterialApi
@Composable
fun topBarView(scaffoldState:BottomSheetScaffoldState){
val scope = rememberCoroutineScope()
TopAppBar(
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
backgroundColor = MaterialTheme.colors.primarySurface,
elevation = 4.dp,
contentPadding = AppBarDefaults.ContentPadding
) {
Row(modifier = Modifier.fillMaxWidth(),verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "返回按钮",
tint = Color.White,
modifier = Modifier
.clickable {
// 打开drawer
scope.launch {
scaffoldState.drawerState.open()
}
}
.padding(start = 12.dp, end = 12.dp)
.fillMaxHeight()
)
Text(text = "页面标题",fontSize = 17.sp,color = Color.White)
}
}
}
二:ModalBottomSheetLayout
先来看看ModalBottomSheetLayout的代码
@Composable
@ExperimentalMaterialApi
fun ModalBottomSheetLayout(
sheetContent: @Composable ColumnScope.() -> Unit,
modifier: Modifier = Modifier,
sheetState: ModalBottomSheetState =
rememberModalBottomSheetState(ModalBottomSheetValue.Hidden),
sheetShape: Shape = MaterialTheme.shapes.large,
sheetElevation: Dp = ModalBottomSheetDefaults.Elevation,
sheetBackgroundColor: Color = MaterialTheme.colors.surface,
sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
content: @Composable () -> Unit
) {...}
- sheetContent 底部抽屉的内容
- modifier 修饰符
- sheetState 设置状态。显示和隐藏底部抽屉 默认实现是rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)。ModalBottomSheetValue.Hidden是隐藏,ModalBottomSheetValue.Expanded打开,ModalBottomSheetValue.HalfExpanded 打开一半
- sheetShape 设置底部抽屉形状
- sheetElevation 设置底部抽屉的阴影
- sheetBackgroundColor 设置底部抽屉的背景颜色
- sheetContentColor 设置底部抽屉内容的颜色
- scrimColor 设置底部抽屉打开的时候,顶部剩余部分的颜色
- content ModalBottomSheetLayout的内容 举例:
@ExperimentalMaterialApi
@Preview()
@Composable
fun modalBottomSheetLayoutTest(){
val sheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
val scope = rememberCoroutineScope()
ModalBottomSheetLayout(
sheetContent = {
Spacer(modifier = Modifier.height(10.dp))
Text(text = " sheetContent title")
Text(text = " sheetContent content")
Text(text = " sheetContent content2")
Text(text = " sheetContent content3")
Text(text = " sheetContent content4")
Text(text = " sheetContent content5")
Text(text = " sheetContent content6")
Text(text = " sheetContent content7")
Text(text = " sheetContent content8")
Text(text = " sheetContent content9")
Spacer(modifier = Modifier.height(10.dp))
},
modifier = Modifier.fillMaxWidth(),
sheetState = sheetState,
sheetShape = RoundedCornerShape(4.dp),
sheetElevation = 16.dp,
sheetBackgroundColor = Color.Red,
sheetContentColor = Color.White,
scrimColor = ModalBottomSheetDefaults.scrimColor)
{
Column {
Spacer(modifier = Modifier.height(10.dp))
Text(text = " ModalBottomSheetLayout title")
Text(text = " ModalBottomSheetLayout content")
Button(onClick = {
scope.launch {
if(sheetState.isVisible) sheetState.hide() else sheetState.show()
}
}) {
Text(text = " 打开")
}
Spacer(modifier = Modifier.height(10.dp))
}
}
}
三:BackdropScaffold
先来看看代码
@Composable
@ExperimentalMaterialApi
fun BackdropScaffold(
appBar: @Composable () -> Unit,
backLayerContent: @Composable () -> Unit,
frontLayerContent: @Composable () -> Unit,
modifier: Modifier = Modifier,
scaffoldState: BackdropScaffoldState = rememberBackdropScaffoldState(Concealed),
gesturesEnabled: Boolean = true,
peekHeight: Dp = BackdropScaffoldDefaults.PeekHeight,
headerHeight: Dp = BackdropScaffoldDefaults.HeaderHeight,
persistentAppBar: Boolean = true,
stickyFrontLayer: Boolean = true,
backLayerBackgroundColor: Color = MaterialTheme.colors.primary,
backLayerContentColor: Color = contentColorFor(backLayerBackgroundColor),
frontLayerShape: Shape = BackdropScaffoldDefaults.frontLayerShape,
frontLayerElevation: Dp = BackdropScaffoldDefaults.FrontLayerElevation,
frontLayerBackgroundColor: Color = MaterialTheme.colors.surface,
frontLayerContentColor: Color = contentColorFor(frontLayerBackgroundColor),
frontLayerScrimColor: Color = BackdropScaffoldDefaults.frontLayerScrimColor,
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) }
) {...}
- appBar 顶部的控件,可用我们之前讲过的TopAppBar TopAppBar讲解
- backLayerContent 显示在后面被遮挡的内容
- frontLayerContent 显示在前面的内容
- modifier 修饰符
- scaffoldState 状态。可以设置snackbar的状态。还可以设置BackdropScaffoldState的状态。有BackdropValue.Concealed. 表示隐藏了后一层,而激活了前一层 跟BackdropValue.Revealed 表示后一层显示,前一层隐藏
- gesturesEnabled 可否可用通过手指拖动的形式显示和隐藏前后界面
- peekHeight 前面的界面举例顶部的距离,也可以理解成后面的界面默认露出显示的高度。默认是56dp
- headerHeight
- persistentAppBar 当为true的时候,不管显示还是隐藏后面的界面,appBar都一直显示的。如果值为false,则显示后面的界面的时候,appBar会隐藏
- stickyFrontLayer 当为true的时候,前面的界面之后下拉到后面界面的内容高度位置。为false 的时候,前面的界面可以一直下拉到屏幕底部(试试效果就知道)
- backLayerBackgroundColor 后面界面的背景颜色
- backLayerContentColor 后面界面的内容的颜色
- frontLayerShape 前面界面的形状
- frontLayerElevation 前面界面的阴影
- frontLayerBackgroundColor 前面界面的背景颜色
- frontLayerContentColor 前面界面的内容的颜色
- frontLayerScrimColor 前面界面下拉时,顶部预留出来的空白的颜色
- snackbarHost 设置Snackbar的 举例:
@ExperimentalMaterialApi
@Preview()
@Composable
fun backdropScaffoldTest(){
val scaffoldState = rememberBackdropScaffoldState(BackdropValue.Concealed)
val scope = rememberCoroutineScope()
BackdropScaffold(
appBar = { topBarView(scaffoldState = scaffoldState) },
backLayerContent = {
Column() {
Text(text = "backLayerContent Title")
Text(text = "backLayerContent Content")
Text(text = "backLayerContent Content1")
Text(text = "backLayerContent Content2")
Text(text = "backLayerContent Content3")
Text(text = "backLayerContent Content4")
Text(text = "backLayerContent Content5")
Text(text = "backLayerContent Content6")
Text(text = "backLayerContent Content7")
Text(text = "backLayerContent Content8")
Text(text = "backLayerContent Content9")
Text(text = "backLayerContent Content10")
}
},
frontLayerContent = {
Column() {
Text(text = "frontLayerContent Title")
Text(text = "frontLayerContent Content")
Text(text = "frontLayerContent Content1")
Text(text = "frontLayerContent Content2")
Text(text = "frontLayerContent Content3")
Text(text = "frontLayerContent Content4")
Text(text = "frontLayerContent Content5")
Text(text = "frontLayerContent Content6")
Text(text = "frontLayerContent Content7")
Text(text = "frontLayerContent Content8")
Text(text = "frontLayerContent Content9")
Text(text = "frontLayerContent Content10")
Button(onClick = {
scope.launch {
scaffoldState.snackbarHostState.showSnackbar("显示了Snackbar的内容","隐藏",SnackbarDuration.Short)
}}) {
Text(text = "打开Snackbar")
}
}
},
scaffoldState = scaffoldState,
gesturesEnabled = true,
peekHeight = 48.dp,
persistentAppBar = true,
stickyFrontLayer = true,
backLayerBackgroundColor = Color.Red,
backLayerContentColor = Color.White,
frontLayerShape = BackdropScaffoldDefaults.frontLayerShape,
frontLayerElevation = BackdropScaffoldDefaults.FrontLayerElevation,
frontLayerBackgroundColor = Color.White,
frontLayerContentColor = Color.Black,
frontLayerScrimColor = BackdropScaffoldDefaults.frontLayerScrimColor,
)
}
@ExperimentalMaterialApi
@Composable
fun topBarView(scaffoldState:BackdropScaffoldState){
val scope = rememberCoroutineScope()
TopAppBar(
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
backgroundColor = MaterialTheme.colors.primarySurface,
elevation = 4.dp,
contentPadding = AppBarDefaults.ContentPadding
) {
Row(modifier = Modifier.fillMaxWidth(),verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "返回按钮",
tint = Color.White,
modifier = Modifier
.clickable {
// 打开drawer
scope.launch {
if (scaffoldState.isConcealed) scaffoldState.reveal() else scaffoldState.conceal()
}
}
.padding(start = 12.dp, end = 12.dp)
.fillMaxHeight()
)
Text(text = "页面标题",fontSize = 17.sp,color = Color.White)
}
}
}