Note that the controls in Jetpack Compose are defined as Composable functions. The controls are officially called Composable, which translates to “Composable items.” I use terms like “controls” or “elements” when emphasizing their presence as part of an interface. I don’t know if there’s a better word, so I’ll just use those two. I normally use the term “composable” when I merely emphasize that it is a composable item. Layout system
The basic principle of
Elements need to measure themselves by constraints that limit the maximum and minimum width and height of an element. If an element has child elements, it measures each child element to help determine its size, and every time an element reports its size to its parent, it gets a chance to place its child elements relative to itself.
Compose does not allow multiple measurements, just like Flutter, because repeated measurements applied to the UI tree result in an exponential performance degradation. Of course, there are times when you need to get information about child elements repeatedly, and there are other ways to do that.
Customize layout Modifier
In Compose, Modifier provides a series of functions that can be used to provide a variety of layout parameters, such as padding, to see how it works.
Extend the Modifier method by extending the function, because the Modifier is called in chain, our extended method should also comply with the chain call rules, the Modifier. Then method is used to assist the chain call, it accepts a Modifier, Returns a Modifier combined with this Modifier.
fun Modifier.firstBaselineToTop( firstBaseLineToTop: Dp ) = this.then( layout { measurable, constraints -> // do something... })Copy the code
The layout inside is also a Modifier method that takes a parameter, which is a lambda, which is where we measure and place the child controls.
__4__, we can set the FristBaseline to the top by using our extended firstBaselineToTop method.
As a first step, we need to measure the child control to obtain a Placeable object that we can use to position the child control relative to the parent control.
layout { measurable, constraints ->
val placeable = measurable.measure(constraints = constraints)
}
Copy the code
You can either pass in the given constraints directly, or you can construct them yourself.
Now that the child control has been measured against the given limits, we need to calculate its height from the top. We should use the height passed in by the user minus the position of FirstBaseline to get how high the control should be from the top.
// Check if the child element has FirstBaseLine check( = AlignmentLine. Unspecified) val firstBaseLine = placeable [firstBaseLine] / / the computational elements are placed in Y, Elements and increase the height of the val placeableY = firstBaseLineToTop. RoundToPx () - firstBaseLine val height = placeable. Height + placeableYCopy the code
Everything is ready. It’s time to place the control.
Use the Measurescope.layout method to report the size to the outside world and lay itself out, which returns a MeasureResult that is exactly what the entire external lambda expression requires.
layout(placeable.width,height) {
placeable.placeRelative(0,placeableY)
}
Copy the code
Complete code:
fun Modifier.firstBaselineToTop( firstBaseLineToTop: Dp ) = this.then( layout { measurable, constraints -> val placeable = measurable.measure(constraints = constraints) check(placeable[FirstBaseline] ! = AlignmentLine.Unspecified) val firstBaseLine = placeable[FirstBaseline] val placeableY = firstBaseLineToTop.roundToPx() - firstBaseLine val height = placeable.height + placeableY layout(placeable.width,height) { placeable.placeRelative(0,placeableY) } } ) @Preview @Composable fun useFirstBaselineToTop() { Column { Text("Hi,there", modifier = Modifier.firstBaselineToTop(24.dp)) } } @Preview @Composable fun usePadding() { Column { Text("Hi,there",modifier = Modifier.padding(top = 24.dp)) } }Copy the code
A custom Layout
Below is a simple custom Column layout. Because and self – defined Modifier almost, not to say.
@Composable fun CustomColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout(modifier = Modifier, content = content) { measurables, Val placeables = measurables.map {it. Measure (constraints = constraints)} // Var yPos = 0 reports the size to the parent element, Here is as big as the parent element layout (constraints. MaxWidth, constraints. MaxHeight) {/ / placed each child element placeables forEach {placeable - > placeable.placeRelative(0,yPos) yPos += placeable.height } } } }Copy the code
Jetpack Compose is more flexible in implementing the UI tree for composition than the traditional View mode. In general, the following points: 1. Each sub-control modifier work, measure, and placed (the next modifier will be placed on the basis of the previous measure, which is why the modifier is sensitive to the order) 2. The parent control measures the size of the child control, (this size is reported by the child control itself, I personally think it should be the last modifier in the chain of the layout, the other layout is the next modifier reported, just my personal opinion, not hope to point out), according to these size to calculate their own size, And reported to the parent control of the parent control, and finally in accordance with their own internal arrangement of the order of the child elements.
Conclusion: the follow-up will continue to update oh, like to pay attention to it. Compose functional programming focus analysis