本文字数:10501字
预计阅读时间:27 分钟
Compose自定义布局的使用
我们知道,在Android View体系下,自定义布局需要继承ViewGroup重写onMeasure、onLayout方法,那么在Compose UI框架中该如何实现自定义布局呢?
今天我们就来学习下Compose UI中自定义布局的具体使用。
实现目标
项目中有一个房源展示页面,用来展示一栋楼的所有房间信息,布局要求如下:
每个房间的宽高尺寸固定,水平方向需要动态计算可以显示的房间数量,内容水平方向居中;
房源数量较少,无法充满屏幕时,房源在屏幕中竖直方向居中显示;
房源数量超过屏幕时,从上向下布局,竖直方向可以滑动查看。
我们以此页面为目标,学习Compose自定义布局的使用。
效果图
效果一:上下、左右居中
效果二:上下滑动
Compose 自定义布局实现方式在编写代码前,我们先来了解下Compose 中自定义布局的实现方式。
Compose中使用Layout 可组合项来实现自定义布局,在Layout函数中完成子元素的测量和放置。以下是 Layout 可组合项的函数签名:
@Composable inline fun Layout(
content: @Composable () -> Unit,
modifier: Modifier = Modifier,
measurePolicy: MeasurePolicy
) {}
一个自定义布局的Layout代码结构通常如下代码所示:
@Composable
fun MyBasicColumn(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier,
content = content
) { measurables, constraints ->
// 1. 使用给定的约束条件constraints测量children
val placeables = measurables.map { measurable ->
measurable.measure(constraints)
}
// 2. 设置布局的尺寸,放置子元素
layout(constraints.maxWidth, constraints.maxHeight) {
var yPosition = 0
//在父布局中放置children
placeables.forEach { placeable ->
placeable.placeRelative(x = 0, y = yPosition)
yPosition += placeable.height
}
}
}
}
从上面代码可以看到,Compose实现自定义布局,主要有两步:
测量每个子元素在父布局约束下的大小
确定布局尺寸,放置子元素
主要参数介绍
Layout函数中,有三个主要参数:
1. modifer
由外部传入的修饰符,用来修饰我们自定义的这Layout 组件的一些属性或约束 Constraints;
2. content
自定义布局 Layout 组件中所包含的子元素 children;
3. measurePolicy
mearsurePolicy 参数是 MeasurePolicy 类型,它是一个函数式接口,指定了布局测量和放置项目的方式。我们通常在Layout函数中以尾随 Lambda 的形式提供 MeasurePolicy 作为参数,从而实现所需的 MeasureScope.measure
函数。
fun interface MeasurePolicy {
fun MeasureScope.measure(
measurables: List<Measurable>,
constraints: Constraints
): MeasureResult
}
measure函数接受一个 Constraints 对象来告知 Layout 它的尺寸限制。Constraints 是一个简单类,用于限制 Layout 的最大和最小宽度与高度, constraints中提供的maxWidth和maxHeight是计算过modifier中padding之后的值, 所以布局中不需要再考虑padding:
class Constraints {
val minWidth: Int
val maxWidth: Int
val minHeight: Int
val maxHeight: Int
}
measure 函数还会接受 List&