← Back to Compose UI
Layout
Component
in
Compose UI
. Since 0.1.0-dev15Overview
Examples
Community Notes
Video
@Composable
fun LayoutUsage(content: @Composable () -> Unit) {
// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
Layout(content) { measurables, constraints ->
// measurables contains one element corresponding to each of our layout children.
// constraints are the constraints that our parent is currently measuring us with.
val childConstraints = Constraints(
minWidth = constraints.minWidth / 2,
minHeight = constraints.minHeight / 2,
maxWidth = if (constraints.hasBoundedWidth) {
constraints.maxWidth / 2
} else {
Constraints.Infinity
},
maxHeight = if (constraints.hasBoundedHeight) {
constraints.maxHeight / 2
} else {
Constraints.Infinity
}
)
// We measure the children with half our constraints, to ensure we can be double
// the size of the children.
val placeables = measurables.map { it.measure(childConstraints) }
val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
// We call layout to set the size of the current layout and to provide the positioning
// of the children. The children are placed relative to the current layout place.
layout(layoutWidth, layoutHeight) {
placeables.forEach {
it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
}
}
}
}
@Composable
fun LayoutWithProvidedIntrinsicsUsage(content: @Composable () -> Unit) {
// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
val measurePolicy = object : MeasurePolicy {
override fun MeasureScope.measure(
measurables: List<Measurable>,
constraints: Constraints
): MeasureResult {
// measurables contains one element corresponding to each of our layout children.
// constraints are the constraints that our parent is currently measuring us with.
val childConstraints = Constraints(
minWidth = constraints.minWidth / 2,
minHeight = constraints.minHeight / 2,
maxWidth = if (constraints.hasBoundedWidth) {
constraints.maxWidth / 2
} else {
Constraints.Infinity
},
maxHeight = if (constraints.hasBoundedHeight) {
constraints.maxHeight / 2
} else {
Constraints.Infinity
}
)
// We measure the children with half our constraints, to ensure we can be double
// the size of the children.
val placeables = measurables.map { it.measure(childConstraints) }
val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
// We call layout to set the size of the current layout and to provide the positioning
// of the children. The children are placed relative to the current layout place.
return layout(layoutWidth, layoutHeight) {
placeables.forEach {
it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
}
}
}
// The min intrinsic width of this layout will be twice the largest min intrinsic
// width of a child. Note that we call minIntrinsicWidth with h / 2 for children,
// since we should be double the size of the children.
override fun IntrinsicMeasureScope.minIntrinsicWidth(
measurables: List<IntrinsicMeasurable>,
height: Int
) = (measurables.map { it.minIntrinsicWidth(height / 2) }.maxByOrNull { it } ?: 0) * 2
override fun IntrinsicMeasureScope.minIntrinsicHeight(
measurables: List<IntrinsicMeasurable>,
width: Int
) = (measurables.map { it.minIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2
override fun IntrinsicMeasureScope.maxIntrinsicWidth(
measurables: List<IntrinsicMeasurable>,
height: Int
) = (measurables.map { it.maxIntrinsicHeight(height / 2) }.maxByOrNull { it } ?: 0) * 2
override fun IntrinsicMeasureScope.maxIntrinsicHeight(
measurables: List<IntrinsicMeasurable>,
width: Int
) = (measurables.map { it.maxIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2
}
Layout(content = content, measurePolicy = measurePolicy)
}
@Composable
fun LayoutUsage(content: @Composable () -> Unit) {
// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
Layout(content) { measurables, constraints ->
// measurables contains one element corresponding to each of our layout children.
// constraints are the constraints that our parent is currently measuring us with.
val childConstraints = Constraints(
minWidth = constraints.minWidth / 2,
minHeight = constraints.minHeight / 2,
maxWidth = if (constraints.hasBoundedWidth) {
constraints.maxWidth / 2
} else {
Constraints.Infinity
},
maxHeight = if (constraints.hasBoundedHeight) {
constraints.maxHeight / 2
} else {
Constraints.Infinity
}
)
// We measure the children with half our constraints, to ensure we can be double
// the size of the children.
val placeables = measurables.map { it.measure(childConstraints) }
val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
// We call layout to set the size of the current layout and to provide the positioning
// of the children. The children are placed relative to the current layout place.
layout(layoutWidth, layoutHeight) {
placeables.forEach {
it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
}
}
}
}
@Composable
fun LayoutWithProvidedIntrinsicsUsage(content: @Composable () -> Unit) {
// We build a layout that will occupy twice as much space as its children,
// and will position them to be bottom right aligned.
val measurePolicy = object : MeasurePolicy {
override fun MeasureScope.measure(
measurables: List<Measurable>,
constraints: Constraints
): MeasureResult {
// measurables contains one element corresponding to each of our layout children.
// constraints are the constraints that our parent is currently measuring us with.
val childConstraints = Constraints(
minWidth = constraints.minWidth / 2,
minHeight = constraints.minHeight / 2,
maxWidth = if (constraints.hasBoundedWidth) {
constraints.maxWidth / 2
} else {
Constraints.Infinity
},
maxHeight = if (constraints.hasBoundedHeight) {
constraints.maxHeight / 2
} else {
Constraints.Infinity
}
)
// We measure the children with half our constraints, to ensure we can be double
// the size of the children.
val placeables = measurables.map { it.measure(childConstraints) }
val layoutWidth = (placeables.maxByOrNull { it.width }?.width ?: 0) * 2
val layoutHeight = (placeables.maxByOrNull { it.height }?.height ?: 0) * 2
// We call layout to set the size of the current layout and to provide the positioning
// of the children. The children are placed relative to the current layout place.
return layout(layoutWidth, layoutHeight) {
placeables.forEach {
it.placeRelative(layoutWidth - it.width, layoutHeight - it.height)
}
}
}
// The min intrinsic width of this layout will be twice the largest min intrinsic
// width of a child. Note that we call minIntrinsicWidth with h / 2 for children,
// since we should be double the size of the children.
override fun IntrinsicMeasureScope.minIntrinsicWidth(
measurables: List<IntrinsicMeasurable>,
height: Int
) = (measurables.map { it.minIntrinsicWidth(height / 2) }.maxByOrNull { it } ?: 0) * 2
override fun IntrinsicMeasureScope.minIntrinsicHeight(
measurables: List<IntrinsicMeasurable>,
width: Int
) = (measurables.map { it.minIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2
override fun IntrinsicMeasureScope.maxIntrinsicWidth(
measurables: List<IntrinsicMeasurable>,
height: Int
) = (measurables.map { it.maxIntrinsicHeight(height / 2) }.maxByOrNull { it } ?: 0) * 2
override fun IntrinsicMeasureScope.maxIntrinsicHeight(
measurables: List<IntrinsicMeasurable>,
width: Int
) = (measurables.map { it.maxIntrinsicHeight(width / 2) }.maxByOrNull { it } ?: 0) * 2
}
Layout(content = content, measurePolicy = measurePolicy)
}
@Composable
fun LayoutWithMultipleContentsUsage(
content1: @Composable () -> Unit,
content2: @Composable () -> Unit,
) {
// We can provide pass a list of two composable lambdas in order to be able to treat
// measureables from each lambda differently.
Layout(listOf(content1, content2)) { (content1Measurables, content2Measurables), constraints ->
val content1Placeables = content1Measurables.map { it.measure(constraints) }
val content2Placeables = content2Measurables.map { it.measure(constraints) }
layout(constraints.maxWidth, constraints.maxHeight) {
var currentX = 0
var currentY = 0
var currentMaxHeight = 0
// we place placeables from content1 as a first line
content1Placeables.forEach {
it.place(currentX, currentY)
currentX += it.width
currentMaxHeight = maxOf(currentMaxHeight, it.height)
}
currentX = 0
currentY = currentMaxHeight
// and placeables from content2 composable as a second line
content2Placeables.forEach {
it.place(currentX, currentY)
currentX += it.width
}
}
}
}
Previous Component← Group
Next ComponentLookaheadLayout →