Android compose custom layout composable
Compose promotes reusability of composables as small chunks that can be enough for some custom layouts by combining built-in composables such as Column, Row, or Box.
However, you might need to build something unique to your app that requires measuring and laying out children manually. For that, you can use the Layout composable. In fact all higher level layouts like Column and Row are built with this.
Principles of layouts in Compose
Some composable functions emit a piece of UI when invoked that is added to a UI tree that will get rendered on the screen. Each emission (or element) has one parent and potentially many children. Also, it has a location within its parent: an (x, y) position, and a size: a width and height.
Elements are asked to measure themselves with Constraints that should be satisfied. Constraints restrict the minimum and maximum width and height of an element. If an element has child elements it may measure each of them to help determine its own size. Once an element reports its own size, it has an opportunity to place its child elements relative to itself. This will be further explained when creating the custom layout.
Compose UI does not permit multi-pass measurement. This means that a layout element may not measure any of its children more than once in order to try different measurement configurations. Single-pass measurement is good for performance, allowing Compose to handle efficiently deep UI trees. If a layout element measured its child twice and that child measured one of its children twice and so on, a single attempt to lay out a whole UI would have to do a lot of work, making it hard to keep your app performing well. However, there are times when you really need additional information on top of what a single child measurement would tell you – for these cases there are ways of doing this, we will talk about them later.
Here is an example of a custom composable layout MyOwnColumn does the same thing as the provided Column.
import androidx.compose.foundation.layout.padding import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.Layout import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.codelab.layouts.ui.LayoutsCodelabTheme @Composable fun MyOwnColumn( 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 child measurable.measure(constraints) } // Track the y co-ord we have placed children up to var yPosition = 0 // Set the size of the layout as big as it can layout(constraints.maxWidth, constraints.maxHeight) { // 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 } } } } @Preview @Composable fun MyOwnColumnPreview() { LayoutsCodelabTheme { Surface(Modifier.padding(8.dp)) { MyOwnColumn { Text("MyOwnColumn") Text("places items") Text("vertically.") Text("We've done it by hand!") } } } }
Reference:
https://github.com/googlecodelabs/android-compose-codelabs
Search within Codexpedia
Search the entire web