Jetpack Compose layout (2) - Material components and layout

Compose was briefly introduced in the previous article "Jetpack Compose Technology Quick Start" , so here we come to learn the layout of Compose. Since the layout involves more content, it will be written separately.
The layout mainly includes: layout basics , Material components and layouts, custom layouts , and using ConstraintLayout in Compose .
image.png

This article focuses on Material components and layout .
Mainly related to: Material中常用组件and Material布局. As shown below:
This article involves the main knowledge points

Common components in Material

Common components include: , 按钮, 文字 Text, 输入框, 图标 Icon, 分割线 Divider, 复选框 CheckBox, 切换组件 Switch, 滑块 Slider, 进度条 ProgressIndicator, 信息提示组件 SnackBar.Tab 和TabRow

Button
Buttons include: Button, TextButton, IconButton, IconToggleButton, RadioButton, FloatingActionButton, ExtendedFloatingActionButton.
Example usage:

Column {
        Row(Modifier.fillMaxWidth()
                .horizontalScroll(rememberScrollState())
        ) {
            //1 纯文字按钮
            TextButton(onClick = {}) {
                Text("TextButton")
            }
            Spacer(modifier = Modifier.width(5.dp))
            //2 普通按钮
            Button(onClick = { /*TODO*/ }) {
                Text(text = "Button")
            }
            Spacer(modifier = Modifier.width(5.dp))
            // 3 带Icon的按钮
            IconButton(onClick = { /*TODO*/ }, modifier = Modifier.requiredWidth(120.dp)) {
                Row(verticalAlignment = Alignment.CenterVertically) {
                    Icon(Icons.Filled.Favorite, contentDescription = "Favorite",
                        modifier = Modifier.size(ButtonDefaults.IconSize)
                    )
                    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
                    Text(text = "IconButton")
                }
            }
        }
        Row {
            Spacer(modifier = Modifier.width(5.dp))
            // 4 IconToggleButton
            IconToggleButton(checked = true, onCheckedChange = {},
                modifier = Modifier.requiredWidth(120.dp)
            ) {
                Text(text = "IconToggleButton")
            }
            Spacer(modifier = Modifier.width(5.dp))
            //5 OutlinedButton
            OutlinedButton(onClick = { /*TODO*/ }) {
                Text(text = "OutlinedButton")
            }
            Spacer(modifier = Modifier.width(5.dp))
            // 6 RadioButton
            RadioButton(selected = true, onClick = { /*TODO*/ })
        }

        //扩展悬浮按钮
        ExtendedFloatingActionButton(
            icon = { Icon(imageVector = Icons.Default.Favorite, contentDescription = "") },
            text = { Text("Like") },
            onClick = { },
        )
    }

Preview effect:
The effect of each button of material

Text Text
is a composable function of plain text, the source code definition is as follows:

@Composable
fun Text(
    text: String,                             //要显示的文本内容
    modifier: Modifier = Modifier,  //修饰符,
    color: Color = Color.Unspecified, //文字颜色
    fontSize: TextUnit = TextUnit.Unspecified,//文字大小
    fontStyle: FontStyle? = null,//字体样式,如:normal和Italic斜体
    fontWeight: FontWeight? = null,//文字线条粗细,
    fontFamily: FontFamily? = null,//字体
    letterSpacing: TextUnit = TextUnit.Unspecified,//文字间距
    textDecoration: TextDecoration? = null,//文字上的装饰,如:None、Underline、LineThrough,默认为None
    textAlign: TextAlign? = null,//文字在水平方向的布局
    lineHeight: TextUnit = TextUnit.Unspecified,//文本段落的行高
    overflow: TextOverflow = TextOverflow.Clip,//文字溢出后的处理方式,方式:Clip、Ellipsis(省略...)和Visible,默认为Clip,即裁剪
    softWrap: Boolean = true,//文本是否应在软换行符处换行,默认值为true,即在会自动换行
    maxLines: Int = Int.MAX_VALUE,//最大行数
    onTextLayout: (TextLayoutResult) -> Unit = {},//新布局更新时的回调,也可理解为文字内容发生变化后的回调
    style: TextStyle = LocalTextStyle.current
) {
  ......
}

Notes have been added for the meaning of each parameter. When using it, it is OK to pass the value to the corresponding parameter according to your own needs. I will not give an example here.

There are two types of input boxes
in the Material library, namely: TextField and OutlineTextField. The parameters of these two input boxes are basically the same. Here I choose to TextFieldintroduce its parameters in detail, and its source code definition:

@Composable
fun TextField(
    value: String,            //输入的文字内容
    onValueChange: (String) -> Unit,//输入框文字内容变化回调函数
    modifier: Modifier = Modifier,  //修饰符
    enabled: Boolean = true,    //是否可用,包括但不限于输入等操作
    readOnly: Boolean = false, //是否只读,控制是否可输入
    textStyle: TextStyle = LocalTextStyle.current,//输入的文字样式
    label: @Composable (() -> Unit)? = null,//输入框的标签,可用理解为输入框的标题
    placeholder: @Composable (() -> Unit)? = null,//无输入内容时,输入框中的提示信息
    leadingIcon: @Composable (() -> Unit)? = null,//输入框起始位置展示一个icon,可选参数
    trailingIcon: @Composable (() -> Unit)? = null,//输入框结束位置展示一个icon,可选参数
    isError: Boolean = false,//标记输入框中内容是否为错误,如果为true,默认情况下,标签、底部指示器和trailingIcon将以错误颜色显示
    visualTransformation: VisualTransformation = VisualTransformation.None,//输入内容的视觉转换,比如:输入密码时用"*"替代
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,//设置输入框可输入类型,支持:Text、Ascii、Number、Phone、Uri、Email、Password、NumberPassword
    keyboardActions: KeyboardActions = KeyboardActions(),//响应键盘操作时的回调
    singleLine: Boolean = false,//是否单行显示
    maxLines: Int = Int.MAX_VALUE,//最大可显示行数
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    shape: Shape =
        MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),//输入框形状
    colors: TextFieldColors = TextFieldDefaults.textFieldColors()//输入框中各种可设置颜色,包括:输入框文字、label、placeholder、background、leadingIconColor、trailingIconColor、indicatorColor、cursorColor(光标)
) {
    ......
}

Comparison of two input boxes:

  • TextField, with a gray background and no outer border by default, its label information is displayed inside the input box when it gets the focus;
  • OutlineTextField, the default transparent background color, has a border, and the label information is displayed on the border line when the focus is obtained;

Example:

Column {
        //--------------------TextField 输入框 未设置onValueChange时,无论输入何内容均显示“你好”,因为输入内容未赋值给value,与Android原生EditText不同
        TextField(
            //输入框中输入的内容
            value = "",
            onValueChange = {},
            //是否单行显示
            singleLine = true,
            // 输入框提示内容
            label = { Text(text = "TextField")},
            //输入框中文字为空时占位内容
            placeholder = { Text(text = "请输入内容")},
            //在输入框左侧显示一个icon
            leadingIcon = {Icon(painter = rememberVectorPainter(image = Icons.Default.Star), contentDescription = "placeholder")},
            //在输入框最右侧显示一个icon
            trailingIcon = {Icon(painter = rememberVectorPainter(image = Icons.Default.Add), contentDescription = "placeholder")},
            //设置输入框输入类型
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
        )
        //--------------------OutlinedTextField 输入框,可输入内容并显示
        val valueState = remember {
            mutableStateOf("")
        }

        OutlinedTextField(
            value = valueState.value,
            onValueChange = {valueState.value = it},
            singleLine = true,
            // 输入框提示内容
            label = { Text(text = "OutlinedTextField")},
            //输入框中文字为空时占位内容
            placeholder = { Text(text = "请输入内容") },
            //在输入框左侧显示一个icon
            leadingIcon = {Icon(painter = rememberVectorPainter(image = Icons.Default.AccountCircle), contentDescription = "placeholder")},
            //在输入框最右侧显示一个icon
            trailingIcon = {Icon(painter = rememberVectorPainter(image = Icons.Default.Add), contentDescription = "placeholder")},
            //设置输入框输入类型
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
        )
    }

The preview effect is as follows:
Two input box preview images

The icon icon
is similar to Image, and some commonly used icons are built in the Compose library, mainly in the Icons class.
Source code definition:

@Composable
fun Icon(
    painter: Painter,      //设置资源
    contentDescription: String?,//描述此图标所代表内容的文本
    modifier: Modifier = Modifier,//修饰符
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)//着色,可以理解为要显示的颜色
) {
    ......
}

Divider The dividing line
is often used to divide the content of the page for easy display. To put it bluntly, it is to draw a line.
Source code definition:

@Composable
fun Divider(
    modifier: Modifier = Modifier,  //修饰符
    color: Color = MaterialTheme.colors.onSurface.copy(alpha = DividerAlpha),//线条颜色
    thickness: Dp = 1.dp,//线条粗细
    startIndent: Dp = 0.dp//线条的起始偏移量
) {
    ......
}


The two composable function parameters of the check box CheckBox and the switching component Switch are similar, and they are merged together for introduction

@Composable
fun Checkbox(
    checked: Boolean,//是否勾选,或是否打开
    onCheckedChange: ((Boolean) -> Unit)?,//状态发生改变时的回调
    modifier: Modifier = Modifier,//修饰符
    enabled: Boolean = true,//是否可以
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    colors: CheckboxColors = CheckboxDefaults.colors()//颜色相关,包括:checkmarkColor、boxColor、borderColor
) {
    ......
}

Example:

Row {
            //--------------------Switch 组件
            val switchState = remember {
                mutableStateOf(false)
            }
            Switch(checked = switchState.value, onCheckedChange = {switchState.value = it})
            //--------------------Checkbox 勾选框
            val checkState = remember {
                mutableStateOf(false)
            }
            Checkbox(checked = checkState.value, onCheckedChange = {checkState.value = it})
        }

Effect:
image.png

The slider Slider
is the same as the Slider of the Android View system.
Analysis source code:

@Composable
fun Slider(
    value: Float,    //值
    onValueChange: (Float) -> Unit,//滑动值发生变化时的回调
    modifier: Modifier = Modifier,//修饰符
    enabled: Boolean = true,//是否可用
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,//可滑动的值的取值范围
    /*@IntRange(from = 0)*/
    steps: Int = 0,//步数,当大于0时,slider会被分为steps+1段,滑动停止时会自动吸附到最近的点上;值为0时,则可连续滑动,不会被分段
    onValueChangeFinished: (() -> Unit)? = null,//值改变结束后的回调
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    colors: SliderColors = SliderDefaults.colors()//颜色相关的
) {
      ......
}

Example:

//--------------------Slider 滑块
        val sliderState = remember {
            mutableStateOf(0f)
        }
        Slider(value = sliderState.value, onValueChange = {sliderState.value = it},steps = 2)

Slider renderings

Progress bar
The progress bar can be combined with functions, the same as the ProgressBar of the Android View system, which is divided into the following three types:

  • ProgressIndicator, the basic progress bar;
  • CircularProgressIndicator, a circular progress bar;
  • LinearProgressIndicator, a linear progress bar;

Select CircularProgressIndicatorfor parametric analysis:

@Composable
fun CircularProgressIndicator(
    /*@FloatRange(from = 0.0, to = 1.0)*/
    progress: Float,//当前的进度
    modifier: Modifier = Modifier,//修饰符
    color: Color = MaterialTheme.colors.primary,//颜色
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth//进度条粗细
) {
    ......
}

Look at the display effect:
Circular progress bar and linear progress bar

Tab and TabRow
are similar to the TabLayout effect in the Android View system. Usually Tab will be used with TabRow.
TabRowIt is fixed 不可滑动. If multiple tabs are needed 可滑动, use ScrollableTabRow
the TabRow parameter description:

@Composable
fun TabRow(
    selectedTabIndex: Int,    //选中的索引
    modifier: Modifier = Modifier,//修饰符
    backgroundColor: Color = MaterialTheme.colors.primarySurface,//背景色
    contentColor: Color = contentColorFor(backgroundColor),//内容颜色
    //指示器
    indicator: @Composable (tabPositions: List<TabPosition>) -> Unit = @Composable { tabPositions ->
        TabRowDefaults.Indicator(
            Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex])
        )
    },
    //选项卡行和下面显示的内容之间提供了一层分隔
    divider: @Composable () -> Unit = @Composable {
        TabRowDefaults.Divider()
    },
    tabs: @Composable () -> Unit //内容,多个Tab组合函数
) {
      ......
}

Example:

//--------------------选项卡 TabRow
        val state = remember { mutableStateOf(0) }
        val titles = listOf("消息", "通讯录", "附近","我")
        TabRow(selectedTabIndex = state.value,modifier = Modifier.height(50.dp)) {
            titles.forEachIndexed {index,text->
                Tab(selected = state.value == index, onClick = { state.value = index }) {
                    VerticalImageText(text = text)
                }
            }
        }

        Spacer(modifier = Modifier.height(10.dp))
        //--------------------可滑动选项卡 TabRow
        val sTabState = remember { mutableStateOf(0) }
        val sTitles = listOf("消息", "通讯录", "附近","我","交友","教育","购物")
        ScrollableTabRow(selectedTabIndex = sTabState.value,
            modifier = Modifier.height(50.dp),
            edgePadding = 0.dp) {
            sTitles.forEachIndexed {index,text->
                Tab(selected = sTabState.value == index, onClick = { sTabState.value = index }) {
                    VerticalImageText(text = text)
                }
            }
        }

Example renderings

The information prompt component SnackBar
is similar to Toast in the Android View system, but SnackBarit can operate buttons. Usually SnackbarHostused in conjunction with the showSnackbar method of snackbarHostState to control the displayed content. It is worth noting that showSnackbar is suspenda function that needs to be 协成called.
Give an example of usage in slot layout

    val scaffoldState = rememberScaffoldState()
    val scope = rememberCoroutineScope()
    Scaffold(
        scaffoldState = scaffoldState,
        //floatingActionButton位置
        floatingActionButtonPosition = FabPosition.Center,//居中
        //添加一个floatingActionButton
        floatingActionButton = {
            FloatingActionButton(onClick = {
                //点击按钮,显示一个SnackBar
                scope.launch {
                    //注意:在协成中调用
                    scaffoldState.snackbarHostState.showSnackbar("你点击了FloatingActionButton",actionLabel = "Done")
                }
            }) {
                Icon(imageVector = Icons.Default.Add, contentDescription = "")
            }
        },
        //是否与bottomBar区域重叠,true叠加,false 不叠加
        isFloatingActionButtonDocked = true,
    ) {
         ...
    }

Material layout

In order to facilitate the development of developers, Material provides a variety of slot layouts, such as: Scaffold, ModalDrawer, BottomSheetScaffold, BackdropScaffold, 选项卡(mentioned above).

Scaffold
slot layout, the parameters in the source code are as follows:

@Composable
fun Scaffold(
    modifier: Modifier = Modifier,//修饰符
    scaffoldState: ScaffoldState = rememberScaffoldState(),//scaffold的状态
    topBar: @Composable () -> Unit = {},//topBar内容
    bottomBar: @Composable () -> Unit = {},//bottomBar的内容
    snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },//信息提示可组合函数
    floatingActionButton: @Composable () -> Unit = {},//floatingActionButton
    floatingActionButtonPosition: FabPosition = FabPosition.End,//floatingActionButton的位置
    isFloatingActionButtonDocked: Boolean = false,//是否与bottomBar区域重叠,true叠加,false 不叠加
    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//槽位布局的主内容
) {
      ......
}

Sample code:

/**
 * 采用Scaffold槽位
 */
@Composable
fun ScaffoldCompose(){
    val scaffoldState = rememberScaffoldState()
    val scope = rememberCoroutineScope()
    Scaffold(
        scaffoldState = scaffoldState,
        //顶部工具栏
        topBar = { TopBar(onMenuClick = {scope.launch {
                //控制抽屉显示与关闭
                scaffoldState.drawerState.apply {
                    if (isOpen) close() else open()
                }
            }
        })},
        //底部工具栏
        bottomBar = {
            BottomAppBar(
                //当floatActionButton与bottomBar重叠时剪切样式
                cutoutShape = MaterialTheme.shapes.small.copy(CornerSize(50.dp)),
                ) {
                VerticalImageText(rememberVectorPainter(Icons.Rounded.Email),"消息")
                VerticalImageText(rememberVectorPainter(Icons.Rounded.Menu),"动态")
            }
        },
        //floatingActionButton位置
        floatingActionButtonPosition = FabPosition.Center,//居中
        //添加一个floatingActionButton
        floatingActionButton = {
            FloatingActionButton(onClick = {
                //点击按钮,显示一个SnackBar
                scope.launch {
                    scaffoldState.snackbarHostState.showSnackbar("你点击了FloatingActionButton",actionLabel = "Done")
                }
            }) {
                Icon(imageVector = Icons.Default.Add, contentDescription = "")
            }
        },
        //是否与bottomBar区域重叠,true叠加,false 不叠加
        isFloatingActionButtonDocked = true,
        drawerContent = {DrawerContent()}
    ) {
        ShowMaterialComponents()
    }
}

renderings
image.png

It's worth noting that BottomAppBarsupports FAB notch with cutoutShapea parameter , which accepts any Shape. For example, FloatingActionButton uses MaterialTheme.shapes.small with a corner size of 50% as the default value for its shape parameter:

bottomBar = {
            BottomAppBar(
                //当floatActionButton与bottomBar重叠时剪切样式
                cutoutShape = MaterialTheme.shapes.small.copy(CornerSize(50.dp)),
                ) {
                  .....
            }
        },

image.png

The ModalDrawer
is above Scaffold, but if you want to implement a ModalDrawer Scaffoldwithout , you can use ModalDrawerthe composable item. It accepts navigation drawer parameters Scaffoldsimilar , so we won't describe each parameter here, 抽屉的显示位置同Scaffold.

@Composable
@OptIn(ExperimentalMaterialApi::class)
fun ModalDrawer(
    drawerContent: @Composable ColumnScope.() -> Unit,
    modifier: Modifier = Modifier,
    drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
    gesturesEnabled: Boolean = true,
    drawerShape: Shape = MaterialTheme.shapes.large,
    drawerElevation: Dp = DrawerDefaults.Elevation,
    drawerBackgroundColor: Color = MaterialTheme.colors.surface,
    drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
    scrimColor: Color = DrawerDefaults.scrimColor,
    content: @Composable () -> Unit //屏幕内容
) {
    ......
}

In addition, if you want the drawer to be placed at the bottom, you can use BottomDrawerimplementation.

val drawerState = rememberBottomDrawerState(BottomDrawerValue.Closed)
BottomDrawer(
    drawerState = drawerState,
    drawerContent = {
        // Drawer content
    }
) {
    // Screen content
}

The bottom action bar (BottomSheetScaffold)
is used to implement the standard bottom action bar, and BottomSheetScaffoldalso accepts "Scaffoldsimilar parameters, such as topBar, floatingActionButtonand snackbarHost. This contains additional parameters that provide how the bottom action bar should be displayed.
BottomSheetScafoldAcceptable parameters are as follows:

@Composable
@ExperimentalMaterialApi
fun BottomSheetScaffold(
    sheetContent: @Composable ColumnScope.() -> Unit,//BottomSheetScaffold的内容
    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
) {
    ......
}

The following example shows that the bottom content can be expanded/collapsed by clicking the floating button/gesture:

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun BottomSheetCompose(){
    val scaffoldState = rememberBottomSheetScaffoldState()
    val scope = rememberCoroutineScope()
    BottomSheetScaffold(
        scaffoldState = scaffoldState, 
        sheetContent = { MySheetContent()},
        sheetPeekHeight = 120.dp,
        floatingActionButton = {
            FloatingActionButton(onClick = {
                    //点击折叠和收起
                      scope.launch {
                          scaffoldState.bottomSheetState.apply {
                              if (isCollapsed) expand() else collapse()
                          }
                      }
                },
                //设置悬浮窗背景色
                backgroundColor = Color.White
            ) {
                Image(painter = painterResource(id = R.drawable.ic_baseline_directions_bike_24), contentDescription = "",
                    //过滤颜色
                    colorFilter = ColorFilter.tint(MaterialTheme.colors.primary)
                )
            }
        }
    ) {
        Text(text = "应用主内容")
    }
}

image.png

Backdrop Scaffold:
Backdrop Scaffold has a two-layer layout, which can be swipe up with gestures to display the content of the lower layer.
BackdropScaffold accepts some additional backdrop parameters. For example, you can use the peekHeight and headerHeight parameters to set the visible height of the back layer and the minimum inactive height of the front layer. Additionally, you can use the gesturesEnabled parameter to toggle whether the backdrop responds to dragging.
The detailed parameters in its source code are as follows:

@Composable
@ExperimentalMaterialApi
fun BackdropScaffold(
    appBar: @Composable () -> Unit,//topBar
    backLayerContent: @Composable () -> Unit,//背景层内容
    frontLayerContent: @Composable () -> Unit,//前层内容
    modifier: Modifier = Modifier,
    scaffoldState: BackdropScaffoldState = rememberBackdropScaffoldState(Concealed),
    gesturesEnabled: Boolean = true,//前层可滑动
    peekHeight: Dp = BackdropScaffoldDefaults.PeekHeight,//背景层可视高度
    headerHeight: Dp = BackdropScaffoldDefaults.HeaderHeight,//前层header的最小非活动高度
    persistentAppBar: Boolean = true,
    stickyFrontLayer: Boolean = true,
    backLayerBackgroundColor: Color = MaterialTheme.colors.primary,//背景层颜色
    backLayerContentColor: Color = contentColorFor(backLayerBackgroundColor),//背景层内容颜色
    frontLayerShape: Shape = BackdropScaffoldDefaults.frontLayerShape,//前景层Shape
    frontLayerElevation: Dp = BackdropScaffoldDefaults.FrontLayerElevation,
    frontLayerBackgroundColor: Color = MaterialTheme.colors.surface,
    frontLayerContentColor: Color = contentColorFor(frontLayerBackgroundColor),
    frontLayerScrimColor: Color = BackdropScaffoldDefaults.frontLayerScrimColor,
    snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) }
) {
      ......
}

The sample code will not be posted, there are too many, please post a rendering.
Effect picture of BackdropScaffold background curtain

Well, so far, we have finished talking about the common components and layout of Material. There is a lot of content, so let's take a look.

github - example source code
gitee - example source code

おすすめ

転載: blog.csdn.net/seevc/article/details/122806058