专栏名称: 谷歌开发者
Google中国官方账号。汇集Android, Chrome, Angular等移动和网络开发技术、Google Play和AdMob等开发者成长、优化和变现平台。
目录
相关文章推荐
36氪  ·  1亿直男也救不了虎扑 ·  昨天  
新浪科技  ·  【#AI大模型写高考作文哪家强# ... ·  2 天前  
51好读  ›  专栏  ›  谷歌开发者

【GDE 分享】一文看懂 Jetpack Compose 布局流程

谷歌开发者  · 公众号  · 科技媒体  · 2025-01-24 17:30

正文

请到「今天看啥」查看全文


MeasurePolicy - 测量策略


fun interface MeasurePolicy {
fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult
}


MeasurePolicy 通过 measure 方法完成测量。这里有两个重要参数:
  • measurables : 等待测量的对象,其实就是当前节点的子节点
  • constraints : 测量约束。节点需要基于当前的 Constaints 进行测量,它规定了节点尺寸的上限和下限,如下:
class Constraints {    val minWidth: Int    val maxWidth: Int    val minHeight: Int    val maxHeight: Int    ...}



Constraints - 测量约束


父节点通过 Constraints 约束子节点的测量。Constraints 非常重要,我们常说 Compose 不怕布局嵌套正是得益于它。反观 Android 原生视图,由于测量阶段的约束不明确,子 View 需要再次请求父 View 给出清楚的 View.MeasureSpec ,导致出现多次绘制。


举几个例子理解一下 Constraints 如何设置:

对于页面的根节点, Activity 的 Window 的长宽就是其 Constraints 的最大长宽。如果是一个垂直可滚动容器的节点,那么它的 Constraints 的 height 应该是 Infinity,因为它可以跨多个屏幕存在。


此外, Modifier 的装饰能力本质也是通过修改 Constraints 完成的。例如 fillMaxWidth 要求被修饰的节点填充整个父容器,所以 Modifier 会在布局阶段将 minHeight/minWidth 对齐 max 组值。关于 Modifier 参与布局的流程,稍后介绍。



三步走实现 - Kotlin 语法优势的体现


举例看一下三步走代码如何实现。

我们实现一个类似 Column 的布局效果,在 measurePolicy#measure 中实现三步走逻辑。
measurePolicy = { // this: MeasureScope    // Step1:Measure each children    val placeables = measurables.map { measurable ->        measurable.measure(constraints)    }
// Step2: Deciee own size val height = placeables.sumOf { it.height } val width = placeables.maxOf { it.width }
layout(width, height) { //this: Placeable.PlacementScope
// Step3: Place children by changing the offset of y co-ord var yPosition = 0
placeables.forEach { placeable -> // Position item on the screen placeable.placeRelative(x = 0, y = yPosition)
// Record the y co-ord placed up to yPosition += placeable.height } }}


  1. 每个 measuable 提供了参与测量的 measure 方法,此处会传入 Constraints,返回的 placeable 中已经存储了测量后的 widht height ,等待 place

  2. 基于各个 placeable w h 计算当前节点的 Size,并通过 layout 方法设置。 layout 方法内会真正的创建 LayoutNode

  3. layout 方法的末参是一个 lambda,这里是第三步摆放子节点的逻辑,通过设置 y 轴的偏移量实现纵向布局,非常简单


特别值得一提的是,通过 meause 一个方法就完成三步走,布局逻辑相对传统的 View 系统更加高效,回想传统自定义 View 你需要分别实现 onMeasure onLayout onDraw 等,逻辑分散,可读性差。


但是这种集中式的写法有一个弊端,需要人为保证代码顺序。试想如果把 layout 写在 measure






请到「今天看啥」查看全文