3 Modifier 和 基础布局

415 阅读2分钟

修饰符(Modifier)

Modifier 功能十分强大,几乎可以说除了决定 UI 具体内容(是一段文本还是一张图片)以外全都可以由 Modifier 设置。

  • 设置尺寸、样式、布局、绘制
  • 处理用户手势(点击、拖拽、滚动)、文本输入
  • 添加信息,如无障碍标签

Modifier 是一个有序不可变的集合,这些设置可以通过链式调用来完成。

    Box(modifier = Modifier.background(Color.Cyan).size(200.dp, 200.dp)){
        Box(modifier = Modifier.background(Color.Green).size(150.dp, 150.dp))
        Box(modifier = Modifier.background(Color.Blue).size(100.dp, 100.dp))
    }

常用的 Modifier :

方法名作用
size 、width、height尺寸
fillMaxSize、fillMaxWidth、fillMaxHeight填充父容器
background 、border、padding背景、边框、间距
clickable、selectable、draggable、scrollable手势处理

Modifier 设置的顺序很重要

Modifier 有序且顺序很重要,不同的顺序会影响最终效果。例如:Modifier 中没有外边距 Margin 系列的设置,都通过 padding 设置。 padding -> background -> padding

//第一个 padding(8.dp) 跟 margin 效果相同
Row(
    Modifier.fillMaxWidth().padding(8.dp).background(Color.Cyan, RoundedCornerShape(12.dp)).padding(6.dp)
) {
    Box(Modifier.background(Color.Red).size(100.dp, 80.dp))
    Spacer(Modifier.width(20.dp))
    Box(Modifier.background(Color.Magenta).height(60.dp).weight(1f))
}

CE81FA54-F751-4C29-8233-8A2019827860.png

类型安全

有些设置是有作用域的,比如:weight 只能在 Row/Column 布局的子元素中使用,matchParentSize 只能再 Box 布局的子元素中使用。

完整的 Modifier 列表

基础布局

557288B3-D2A8-4CE4-9B5F-5F4182BEBDA7.png

Box

像 View 体系中的 FrameLayout 一样,容器中的子元素按顺序由下到上依次堆叠。不使用 modifier 指定 size 时 Box 大小由子元素决定,类似 warp_content

@Composable
fun BoxBasic(){
    Box(modifier = Modifier.background(Color.Cyan).size(200.dp, 200.dp)){
        Box(modifier = Modifier.background(Color.Green).size(150.dp, 150.dp))
        Box(modifier = Modifier.background(Color.Blue).size(100.dp, 100.dp))
    }
}

A5414D34-3B8B-4D3F-8FF2-3C1C5D070131.png

统一管理子元素的对齐使用 contentAlignment 参数

子元素单独设置对齐使用 modifier.align() 方法

fun BoxBasic(){
    Box(modifier = Modifier.background(Color.Cyan).size(200.dp, 200.dp),
        contentAlignment = Alignment.Center
    ){
        Box(modifier = Modifier.background(Color.Green).size(150.dp, 150.dp))
        //Box(modifier = Modifier.background(Color.Blue).size(100.dp,100.dp)) 下左图
        Box(modifier = Modifier.background(Color.Blue).size(100.dp,100.dp).align(Alignment.BottomEnd))
    }
}

image.png

Column / Row

垂直(Column)/水平(Row)方向的 LinearLayout 。不使用 modifier 指定 size 时大小由子元素决定,相当于 warp_contentverticalArrangementhorizontalAlignment 统一设置子元素的水平/垂直对齐方式。当子元素设置 modifier.weight() 时会在垂直(Column)/水平(Row)方向上占满父容器剩余空间,相当于 match_parent

    Column(
        modifier = Modifier.fillMaxWidth().background(Color.Cyan).padding(20.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Box(modifier = Modifier.background(Color.Yellow).size(200.dp,60.dp))
        Box(modifier = Modifier.background(Color.Magenta).size(200.dp,60.dp).align(Alignment.Start))
        Box(modifier = Modifier.background(Color.LightGray).size(200.dp,60.dp).align(Alignment.End))
    }

B11D2BB1-CD19-4FA7-B8B3-ADB21AB9A5C7.png

    Row(
        modifier = Modifier.height(200.dp).background(Color.Cyan).padding(20.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Box(modifier = Modifier.background(Color.Yellow).size(100.dp,60.dp))
        Box(modifier = Modifier.background(Color.Magenta).size(100.dp,60.dp).align(Alignment.Top))
        Box(modifier = Modifier.background(Color.LightGray).size(100.dp,60.dp).align(Alignment.Bottom))
    }

1451DD28-9AB7-4DCE-B7FD-13A88EC28E8B.png

Column 的verticalArrangement

column_arrangement_visualization.gif

Row 的 horizontalArrangement

row_arrangement_visualization.gif

Spacer

没有内容的仅占位,可以设置宽高或单独设置宽单独设置高。

Row(
    Modifier.fillMaxWidth().padding(8.dp).background(Color.Cyan, RoundedCornerShape(12.dp)).padding(6.dp)
) {
    Box(Modifier.background(Color.Red).size(100.dp, 80.dp))
    Spacer(Modifier.width(20.dp))
    Box(Modifier.background(Color.Magenta).height(60.dp).weight(1f))
}