深入Jetpack Compose——布局原理与自定义布局(三)
在上一篇[文章](深入Jetpack Compose——布局原理与自定义布局(二))中,我们探索了Modifier
的本质和原理。这一次我们看看Compose体系中的一个重要特性:固有特性测量
。
固有特性测量
或许不少人已经知道,Compose为了提高测绘性能,强行规定了每个微件只能被测量一次。也就是说,我们不能写出类似下面这样的代码:
1 | val placeables = measurables.map { it.measure(constrains) } |
一个小问题
那么接下来我们看一个小例子。我们想实现一个菜单,菜单里面有几个菜单栏。于是我们写出了类似这样按的代码
但是效果不怎么样,因为每个Text
的宽度不一样。看起来有点丑
你可能会说,要解决这个问题很简单,为每个Text
添加修饰符fillMaxWidth
,让它占满即可。效果如下:
但是这样新的问题来了:由于每个Text
的Constraint
的maxWidth
都是最大值,于是咱们的Column
宽度也是最大值。于是这个菜单占满了全部屏幕空间。这可不妙!
要解决这个问题,我们只需要为Column
添加这样一个修饰符
1 | Modifier.width(IntrinsicSize.Max) |
它的宽度就是子微件宽度的最大值啦
有Max
应该就有Min
,咱们试试?
宽度变窄了!很神奇吗?这就是固有特性测量的功劳。
(如果你好奇为什么最小宽度是这个,因为子微件是文本,而文本的最小宽度是它每行能容纳一个词时的宽度。在这个例子中,就是Send Feedback分成 Send \n Feedback时Feedback这行字的宽度)
上面的例子中,Column
就适配了固有特性测量这一特性。接下来,我们把自己的实现的VerticalLayout
也来适应一下(VerticalLayout具体实现见第一篇)。
适配固有特性测量
让我们重新把目光转向Layout
1 | inline fun Layout( |
之前对于第三个参数,我们是写成了SAM的形式。我们现在再来看看这个MeasurePolicy
1 |
|
measure
方法是我们之前就用过的,而其余几个拓展函数就是我们要适配 固有特性测量
所需要重写的啦。举个栗子,使用 Modifier.width(IntrinsicSize.Max)
,则会调用 maxIntrinsicWidth
方法,其余同理。
接下来,咱们开干。先挑一个吧
1 | override fun IntrinsicMeasureScope.maxIntrinsicWidth( |
我们以子微件宽度的最大值作为最大约束
1 | override fun IntrinsicMeasureScope.maxIntrinsicWidth( |
效果如下:
min的情况也差不多,效果如下:
完整代码参见Github仓库
后续
关于固有特性测量我们就先看这些。下一篇,我们将探索ParentData
和其它特性,继续我们的布局之旅
本文参考:
本文所有代码见:此处