【Compose 系列】第 4 篇:布局与 Modifier,写界面不走弯路

定位:入门 / 常用技能 适合:能写单个组件,但一排版就乱、Modifier 顺序总是搞反的同学


一、Compose 布局的心智:先「测量」后「摆放」

Compose 的布局分三步:测量 → 摆放 → 绘制 ,而且有个铁律:每个子组件只被测量一次 。这一点和传统 ViewonMeasure(父子可以来回协商多次)很不一样。

对小白来说,你只需要记住三块积木,能解决 90% 的排版:

  • Column:竖着排(垂直方向)。
  • Row:横着排(水平方向)。
  • Box:叠着排(类似 FrameLayout,后写的盖在前写的上面)。

配合 Modifier(修饰符)控制大小、边距、背景、点击等。


二、Modifier 顺序:最容易踩的坑

Modifier 可以链式调用,但顺序会显著影响结果。看这个经典案例:

kotlin 复制代码
// 案例 A:先 padding,再 background
Box(
    modifier = Modifier
        .padding(20.dp)
        .background(Color.Red)
)

// 案例 B:先 background,再 padding
Box(
    modifier = Modifier
        .background(Color.Red)
        .padding(20.dp)
)

结果完全不同:

  • 案例 A:先在四周留出 20dp 空白,再在剩余区域画红色背景。红色区域被 padding 挤小了。
  • 案例 B:先画满红色背景,再在红色内部留 20dp 空白。红色区域撑满原尺寸。

一句话记忆:Modifier 是从外到内、从左到右依次「包裹」的。左边的先作用在外层,右边的作用在内层。

想清楚这条,sizeclickableclip 等顺序问题都能自己推出来。


三、常用布局速查表

需求 用什么 关键参数
竖排 Column verticalArrangement(主轴间距)、horizontalAlignment(交叉轴对齐)
横排 Row horizontalArrangementverticalAlignment
叠放/定位 Box Alignment
复杂约束 ConstraintLayout createRefs、约束关系
铺满 Modifier.fillMaxSize() 注意 fillMaxWidth/fillMaxHeight
间距 Modifier.padding() 四边或单边
宽高 Modifier.size(width, height) 固定尺寸

Arrangement 控制主轴上的间距(SpaceBetweenSpaceAroundspacedBy),Alignment 控制交叉轴上的对齐。这两个词区分清楚,排版就通了一半。


四、Scaffold:页面的「骨架」

写一个标准页面,别从零堆 Column,直接用 Scaffold。它帮你准备好 TopBar(顶栏)、BottomBar(底栏)、FloatingActionButton(悬浮按钮)和内容区。

kotlin 复制代码
Scaffold(
    topBar = { TopAppBar(title = { Text("标题") }) },
    bottomBar = { BottomAppBar { Text("底栏") } },
    floatingActionButton = { FloatingActionButton(onClick = {}) { Text("+") } }
) { innerPadding ->
    // 内容区:务必应用 innerPadding,否则会被系统栏/顶栏挡住
    Column(modifier = Modifier.padding(innerPadding)) {
        Text("页面内容")
    }
}

小白最容易忘的是 innerPaddingScaffold 的 lambda 会传给你一个 PaddingValues,它包含了顶栏、底栏、系统状态栏占用的空间。内容区一定要 Modifier.padding(innerPadding),否则内容会被遮挡。


五、Material 3 主题:一套配色吃遍天下

Compose 默认基于 Material 3 。你不需要手写颜色值,而是通过 MaterialTheme.colorScheme 取语义化颜色:

kotlin 复制代码
Text(color = MaterialTheme.colorScheme.primary)          // 主色
Surface(color = MaterialTheme.colorScheme.surface)       // 表面色

好处:换主题(浅色/深色)时,整套颜色自动切换。做暗黑模式几乎零成本。MaterialTheme 是文章 demo 里到处出现的外层包裹,本质就是给子树提供「主题环境」。


六、资深开发者的醍醐灌顶时刻

  1. Compose 的布局不是 ViewGroup 的翻版 。没有 onMeasure 的多轮协商,测量是单遍的。这意味着自定义布局要自己实现测量逻辑 (第 11 篇),但也避免了 View 体系里 MeasureSpec 的坑。
  2. Modifier 是「不可变链」。每个 Modifier 都是一个包装对象,链式调用会生成嵌套结构。顺序决定嵌套层级,所以顺序即语义。
  3. paddingclickable 前后,点击区域不同clickable 在外层时,padding 区域也可点击;clickable 在内层时,padding 区域不可点击。这是一个真实生产 bug 高发点。
  4. 别滥用 Box 做绝对定位 。优先用 Column/Row + Arrangement/Alignment,语义更清晰,也更容易适配不同屏幕。

七、动手题

写一个「个人信息卡片」:头像圆形、姓名在右侧、下方一行简介,整体卡片有圆角、阴影、内边距。用 RowColumnBoxModifier 完成,特别注意 Modifier 顺序。


八、学习资料

(下一篇预告:状态管理进阶,StateFlow + ViewModel 的工程级架构。)

相关推荐
一个用户名i2 小时前
【Compose 系列】第 3 篇:状态管理入门,让界面「动」起来
android jetpack
alexhilton1 天前
规范驱动开发:让AI生成符合预期的KMP代码
android·kotlin·android jetpack
一个用户名i3 天前
【Compose 系列】第 1 篇:认识 Compose,为什么要学它
android·android jetpack
我命由我123455 天前
Android 开发问题:unexpected element <service> found in <manifest>
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
我命由我123455 天前
Android 开发问题:TopAppBar 和 topAppBarColors API is experimental...
android·java·java-ee·kotlin·android studio·android jetpack·android-studio
alexhilton8 天前
千万别误用Android Skills
android·kotlin·android jetpack
XiaoLeisj10 天前
Kotlin Flow 常用操作符:数据变换 map、filter、onEach,时间控制 debounce、sample,终端聚合 reduce、fold
android·kotlin·android jetpack·协程·响应式编程·flow
XiaoLeisj11 天前
Kotlin Flow:冷流收集、并行订阅、emit 推送、delay 延迟、collect 全量收集与 collectLatest 的实时数据处理
android·kotlin·android jetpack·协程·flow
我命由我1234512 天前
Jetpack Compose - @Preview 注解
android·java·java-ee·android studio·android jetpack·android-studio·android runtime