In the last article( In depth jetpack composition - layout principle and custom layout (II) In, we explored the essence and principle of Modifier. This time, let's look at an important feature in the Compose system: inherent characteristic measurement.
Inherent characteristic measurement
Perhaps many people already know that in order to improve the mapping performance, Compose forcibly stipulates that each widget can only be measured once. In other words, we can't write code like this:
val placeables = measurables.map { it.measure(constrains) } // Try to measure the second time and report the error directly val placeablesSecond = measurables.map { it.measure(constrains) }
A small problem
Then let's look at a small example. We want to implement a menu with several menu bars. So we wrote code like this
But the effect is not good, because the width of each Text is different. It looks a little ugly
You might say that it's easy to solve this problem by adding the modifier fillMaxWidth to each Text and making it full. The effect is as follows:
But here comes a new problem: since the maxWidth of each Text Constraint is the maximum, our Column width is also the maximum. So this menu takes up all the screen space. That's not good!
To solve this problem, we only need to add such a modifier to the Column
Modifier.width(IntrinsicSize.Max)
Its width is the maximum width of the sub widget
If there is Max, there should be Min. let's try it?
The width has narrowed! Is it amazing? This is the credit of inherent characteristic measurement.
(if you are curious why the minimum width is this, because the widget is text, and the minimum width of the text is the width when it can hold one word per line. In this example, it is the width of the line of feed when Send Feedback is divided into Send \n Feedback.)
In the above example, Column is adapted to the inherent characteristic measurement. Next, let's adapt our own implementation of vertical layout (see Chapter 1 for the specific implementation of vertical layout).
Adaptive natural characteristic measurement
Let's turn our attention to Layout again
@Composable inline fun Layout( content: @Composable () -> Unit, modifier: Modifier = Modifier, measurePolicy: MeasurePolicy )
Previously, for the third parameter, we wrote it in the form of SAM. Now let's take a look at the MeasurePolicy
@Stable fun interface MeasurePolicy { fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult /** * The function used to calculate [IntrinsicMeasurable.minIntrinsicWidth]. It represents * the minimum width this layout can take, given a specific height, such that the content * of the layout can be painted correctly. */ fun IntrinsicMeasureScope.minIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int fun IntrinsicMeasureScope.minIntrinsicHeight( measurables: List<IntrinsicMeasurable>, width: Int ): Int fun IntrinsicMeasureScope.maxIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int fun IntrinsicMeasureScope.maxIntrinsicHeight( measurables: List<IntrinsicMeasurable>, width: Int ): Int }
We have used the measure method before, and the other expansion functions are what we need to rewrite to adapt to the measurement of inherent characteristics. For example, use modifier Width (intrinsicsize. Max), the maxIntrinsicWidth method will be called, and the rest are the same.
Next, let's do it. Pick one first
override fun IntrinsicMeasureScope.maxIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { TODO("Not yet implemented") }
We take the maximum width of the sub widget as the maximum constraint
override fun IntrinsicMeasureScope.maxIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { var width = 0 measurables.forEach { val childWidth = it.maxIntrinsicWidth(height) if(childWidth > width) width = childWidth } return width }
The effect is as follows:
(width is based on the word Funny)min is similar, and the effect is as follows:
(width is based on the word is)See Github warehouse for complete code
follow-up
Let's look at these first about the measurement of inherent characteristics. In the next article, we will explore ParentData and other features to continue our layout journey
Reference:
- Talk about the inherent characteristic measurement of Compose - Intrinsic Nuggets (juejin.cn)
- Official Android Video: Deep dive into Jetpack Compose layouts
For all codes in this article, see: here