[go: nahoru, domu]

blob: b42df5a4a47005edb665d0581c64f38d9ac7e8df [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.ui.core.samples
import androidx.annotation.Sampled
import androidx.compose.Composable
import androidx.ui.core.Constraints
import androidx.ui.core.ExperimentalLayoutNodeApi
import androidx.ui.core.Layout
import androidx.ui.core.Modifier
import androidx.ui.core.id
import androidx.ui.core.layoutId
import androidx.compose.foundation.Box
import androidx.ui.core.measureBlocksOf
@Sampled
@Composable
fun LayoutWithProvidedIntrinsicsUsage(children: @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(
children,
minIntrinsicWidthMeasureBlock = { measurables, h ->
// 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.
(measurables.map { it.minIntrinsicWidth(h / 2) }.maxByOrNull { it } ?: 0) * 2
},
minIntrinsicHeightMeasureBlock = { measurables, w ->
(measurables.map { it.minIntrinsicHeight(w / 2) }.maxByOrNull { it } ?: 0) * 2
},
maxIntrinsicWidthMeasureBlock = { measurables, h ->
(measurables.map { it.maxIntrinsicHeight(h / 2) }.maxByOrNull { it } ?: 0) * 2
},
maxIntrinsicHeightMeasureBlock = { measurables, w ->
(measurables.map { it.maxIntrinsicHeight(w / 2) }.maxByOrNull { it } ?: 0) * 2
}
) { 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 = constraints.maxWidth / 2,
maxHeight = constraints.maxHeight / 2
)
// 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.place(layoutWidth - it.width, layoutHeight - it.height) }
}
}
}
@Sampled
@Composable
@OptIn(ExperimentalLayoutNodeApi::class)
fun LayoutWithMeasureBlocksWithIntrinsicUsage(children: @Composable () -> Unit) {
val measureBlocks = measureBlocksOf(
minIntrinsicWidthMeasureBlock = { measurables, h ->
// 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.
(measurables.map { it.minIntrinsicWidth(h / 2) }.maxByOrNull { it } ?: 0) * 2
},
minIntrinsicHeightMeasureBlock = { measurables, w ->
(measurables.map { it.minIntrinsicHeight(w / 2) }.maxByOrNull { it } ?: 0) * 2
},
maxIntrinsicWidthMeasureBlock = { measurables, h ->
(measurables.map { it.maxIntrinsicHeight(h / 2) }.maxByOrNull { it } ?: 0) * 2
},
maxIntrinsicHeightMeasureBlock = { measurables, w ->
(measurables.map { it.maxIntrinsicHeight(w / 2) }.maxByOrNull { it } ?: 0) * 2
}
) { 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 = constraints.maxWidth / 2,
maxHeight = constraints.maxHeight / 2
)
// 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.place(layoutWidth - it.width, layoutHeight - it.height) }
}
}
Layout(children = children, measureBlocks = measureBlocks)
}
@Sampled
@Composable
fun LayoutUsage(children: @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(children) { 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 = constraints.maxWidth / 2,
maxHeight = constraints.maxHeight / 2
)
// 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.place(layoutWidth - it.width, layoutHeight - it.height) }
}
}
}
@Sampled
@Composable
fun LayoutTagChildrenUsage(header: @Composable () -> Unit, footer: @Composable () -> Unit) {
Layout({
// Here the Containers are only needed to apply the modifiers. You could use the
// modifier on header and footer directly if they are composables accepting modifiers.
Box(Modifier.layoutId("header"), children = header)
Box(Modifier.layoutId("footer"), children = footer)
}) { measurables, constraints ->
val placeables = measurables.map { measurable ->
when (measurable.id) {
// You should use appropriate constraints. Here we measure with dummy constraints.
"header" -> measurable.measure(Constraints.fixed(100, 100))
"footer" -> measurable.measure(constraints)
else -> error("Unexpected tag")
}
}
// Size should be derived from children measured sizes on placeables,
// but this is simplified for the purposes of the example.
layout(100, 100) {
placeables.forEach { it.place(0, 0) }
}
}
}