New pit for compose custom layout. Forget the basics and get straight to the point.

As we know, in the view system, custom Layout requires the view to integrate the ViewGroup and rewrite the onMeasure and onLayout methods. In Compse, the compose method is used, and the structure is as follows:

Take a custom Column as an example:

1. First we define our own cpmPose function

@Composablefun 
MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
)
Copy the code

This method contains the most basic two inputs, the modifier modifier and the lamda expression annotated by @composable as the contents of the subitem

2. Look at the operation of a specific function body

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // Don't constrain child views further, measure them with given constraints
        // List of measured children
        val placeables = measurables.map { measurable ->
            // Measure each children
            measurable.measure(constraints)
        }
        // Set the size of the layout as big as it can
        layout(constraints.maxWidth, constraints.maxHeight) {
            // Track the y co-ord we have placed children up to
            var yPosition = 0
            // Place children in the parent layout
            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
            }
        }
    }
}
Copy the code

The code is copied from the official website, the correctness is needless to say, specific analysis of the role.

1. Use the defined Layout method in the function body. In compose, all component definitions use methods. For example, in compose, all component definitions use methods. For example, in compose, all component definitions use methods. The last argument to the function receives modifiers and content using the lamda) Layout method of the @composable annotations. The callback sends measurables and constraints. You can guess what these two parameters do from their names

  • I’m a measurables kid
  • Constraints: Parent class constraints

The Layout function’s lamda comes from the third input parameter, MeasurePolicy, which is an interface whose callback comes from the above two parameters:

fun MeasureScope.measure(
    measurables: List<Measurable>,
    constraints: Constraints
): MeasureResult
Copy the code

Measurables are measurable calls and constraints are passed in. It is equivalent to measuring each child control according to the constraints of its parent control. It is similar to measurables in views system.

Lamda (width,heigiht); lamda (width,heigiht); lamda (height,heigiht); lamda (width,heigiht); lamda (height,heigiht); lamda (width,heigiht) The place method is called for each of them (there are several like it, placeRelative is used here), passing in coordinates to complete the layout of the child views

Here a custom layout is completed, in fact, and the following views system is very similar, but also similar two steps:

1. Measure the size of each child view under the constraints of the parent view

2, walk through the child view, use layout method to put each view in the correct position.

More of the same

3, About layout (note the lowercase)

Here’s a quote from the official website:

You can use the Layout modifier to change how elements are measured and laid out. Layout is a lambda; Its parameters include elements that you can measure (passed in __4__ form) and the incoming constraints on that composable (passed in __4__ form)

Here’s another code:

fun Modifier.firstBaselineToTop( firstBaselineToTop: Dp) = layout { measurable, constraints -> // Measure the composable val placeable = measurable.measure(constraints) // Check the composable has a first baseline check(placeable[FirstBaseline] ! = AlignmentLine.Unspecified) val firstBaseline = placeable[FirstBaseline] // Height of the composable with padding - first baseline val placeableY = firstBaselineToTop.roundToPx() - firstBaseline val height = placeable.height + placeableY layout(placeable.width, height) { // Where the composable gets placed placeable.placeRelative(0, placeableY) }}Copy the code

This is how you can change the text baseline top padding. The modifier extension function is __4__, the callback parameter is __4__, and the layout function is __4__.

Here is the end of the custom layout, custom layout difficulty is mainly in the child view in the parent view constraints under the layout logic, you can also see that the transplant before the custom layout of views should be relatively easy, the coordinate calculation logic is removed, and then you can easily complete the transplant. For example, compose uses the last lamda parameter in fun. Because of kotlin’s syntax, it is easy to think of lamda as the body of a function. In fun, only fun is called, and the execution of the function is hidden.