Row
横向线性布局和竖向线性布局很像,都属于线性布局,不同的是竖向线性布局在屏幕上垂直排列,而横向线性布局在屏幕上水平排列:
在Android View中,实现横向线性布局也是LinearLayout,只需要修改orientation就可以自由切换横向纵向,但是在Compose中横向和纵向是两个不同的控件,但又有很多相同之处,我们先看一个例子:
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically)
{
DefaultText("Text1") // 控件1
DefaultText("Text2") // 控件2
DefaultText("Text3") // 控件3
}
我们看到三个Text组件水平排列,并且横向和纵向都居中。同Column一样,我们看看Row的源码:
@Composable
inline fun Row(
modifier: Modifier = Modifier,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.Top,
content: @Composable RowScope.() -> Unit
) {
val measurePolicy = rowMeasurePolicy(horizontalArrangement, verticalAlignment)
Layout(
content = { RowScopeInstance.content() },
measurePolicy = measurePolicy,
modifier = modifier
)
}
modifier
Row的修饰符。
horizontalArrangement
布局子控件的水平排列方式。
verticalAlignment
布局子控件的垂直排列方式。
content
Row中子控件。
我们发现Row的参数和Column基本一样,大同小异。我们在Column中学习过Alignment和Arrangement,下面我们看看horizontalArrangement:
@Stable
val Start = object : Horizontal {
// 省略...
}
@Stable
val End = object : Horizontal {
// 省略...
}
实现Arrangement。Horizontal接口的只有上面的两个类,剩下的就是前面说过的实现HorizontalOrVertiacal接口的类了,HorizontalOrVertical中也学习了,这里就不说了。 接下来看看verticalAlignment:
@Stable
fun interface Alignment {
@Stable
fun interface Horizontal {
// 省略...
}
@Stable
fun interface Vertical {
// 省略...
}
companion object {
// 2D Alignments.
@Stable
val TopStart: Alignment = BiasAlignment(-1f, -1f)
@Stable
val TopCenter: Alignment = BiasAlignment(0f, -1f)
@Stable
val TopEnd: Alignment = BiasAlignment(1f, -1f)
@Stable
val CenterStart: Alignment = BiasAlignment(-1f, 0f)
@Stable
val Center: Alignment = BiasAlignment(0f, 0f)
@Stable
val CenterEnd: Alignment = BiasAlignment(1f, 0f)
@Stable
val BottomStart: Alignment = BiasAlignment(-1f, 1f)
@Stable
val BottomCenter: Alignment = BiasAlignment(0f, 1f)
@Stable
val BottomEnd: Alignment = BiasAlignment(1f, 1f)
// 1D Alignment.Verticals.
@Stable
val Top: Vertical = BiasAlignment.Vertical(-1f)
@Stable
val CenterVertically: Vertical = BiasAlignment.Vertical(0f)
@Stable
val Bottom: Vertical = BiasAlignment.Vertical(1f)
// 1D Alignment.Horizontals.
@Stable
val Start: Horizontal = BiasAlignment.Horizontal(-1f)
@Stable
val CenterHorizontally: Horizontal = BiasAlignment.Horizontal(0f)
@Stable
val End: Horizontal = BiasAlignment.Horizontal(1f)
}
}
verticalAlignment和Column中的horizontalAlignment也类似。到现在我们线性布局都学完了,下面我们再看看帧布局Box。
Box
Box是帧布局,同Android View中的FrameLayout:
Box {
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
modifier = Modifier.size(200.dp, 200.dp),
contentDescription = "这是一张图片",
alignment = Alignment.Center,
alpha = 1.0f,
colorFilter = ColorFilter.tint(Color.Red)
)
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
modifier = Modifier.size(100.dp, 100.dp),
contentDescription = "这是一张图片",
alignment = Alignment.Center,
alpha = 1.0f,
colorFilter = ColorFilter.tint(Color.Green)
)
}
它可以将控件进行堆叠,后面的子控件直接覆盖在前面的子控件子上,将前面子控件的部分或全部遮挡,如上图。先看看Box的源码:
@Composable
inline fun Box(
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
propagateMinConstraints: Boolean = false,
content: @Composable BoxScope.() -> Unit
) {
val measurePolicy = rememberBoxMeasurePolicy(contentAlignment, propagateMinConstraints)
Layout(
content = { BoxScopeInstance.content() },
measurePolicy = measurePolicy,
modifier = modifier
)
}
可以看到Box也有排列方式,之前Column和Row的排列方式是Alignment.Horizontal或Alignment.Vertical,但是这里显示类型是Alignment,我们看看Alignment接口有哪些:
companion object {
// 2D Alignments.
@Stable
val TopStart: Alignment = BiasAlignment(-1f, -1f)
@Stable
val TopCenter: Alignment = BiasAlignment(0f, -1f)
@Stable
val TopEnd: Alignment = BiasAlignment(1f, -1f)
@Stable
val CenterStart: Alignment = BiasAlignment(-1f, 0f)
@Stable
val Center: Alignment = BiasAlignment(0f, 0f)
@Stable
val CenterEnd: Alignment = BiasAlignment(1f, 0f)
@Stable
val BottomStart: Alignment = BiasAlignment(-1f, 1f)
@Stable
val BottomCenter: Alignment = BiasAlignment(0f, 1f)
@Stable
val BottomEnd: Alignment = BiasAlignment(1f, 1f)
// 1D Alignment.Verticals.
@Stable
val Top: Vertical = BiasAlignment.Vertical(-1f)
@Stable
val CenterVertically: Vertical = BiasAlignment.Vertical(0f)
@Stable
val Bottom: Vertical = BiasAlignment.Vertical(1f)
// 1D Alignment.Horizontals.
@Stable
val Start: Horizontal = BiasAlignment.Horizontal(-1f)
@Stable
val CenterHorizontally: Horizontal = BiasAlignment.Horizontal(0f)
@Stable
val End: Horizontal = BiasAlignment.Horizontal(1f)
}
分别为顶部、中间、结尾,中间开始、中间、结尾,底部开始、中间和结尾。我们下面通过一个例子,来更深入了解下其排列方式:
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Row {
Box(
contentAlignment = Alignment.TopStart,
modifier = Modifier.size(100.dp).background(Color.Gray),
) {
Text("1", fontSize = 20.sp)
}
Box(
contentAlignment = Alignment.TopCenter,
modifier = Modifier.size(100.dp).background(Color.Magenta),
) {
Text("2", fontSize = 20.sp)
}
Box(
contentAlignment = Alignment.TopEnd,
modifier = Modifier.size(100.dp).background(Color.Cyan),
) {
Text("3", fontSize = 20.sp)
}
}
Row {
Box(
contentAlignment = Alignment.CenterStart,
modifier = Modifier.size(100.dp).background(Color.DarkGray),
) {
Text("4", fontSize = 20.sp)
}
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.size(100.dp).background(Color.Green),
) {
Text("5", fontSize = 20.sp)
}
Box(
contentAlignment = Alignment.CenterEnd,
modifier = Modifier.size(100.dp).background(Color.Red),
) {
Text("6", fontSize = 20.sp)
}
}
Row {
Box(
contentAlignment = Alignment.BottomStart,
modifier = Modifier.size(100.dp).background(Color.Magenta),
) {
Text("7", fontSize = 20.sp)
}
Box(
contentAlignment = Alignment.BottomCenter,
modifier = Modifier.size(100.dp).background(Color.Yellow),
) {
Text("8", fontSize = 20.sp)
}
Box(
contentAlignment = Alignment.BottomEnd,
modifier = Modifier.size(100.dp).background(Color.Magenta),
) {
Text("9", fontSize = 20.sp)
}
}
}
结合了之前学习的Column和Row,运用Box的contentAlignment参数控制其内容的对齐方式,来看看效果:
结果和我们预期的一致,分别为顶部开始、中间、结尾,中间开始、中间、结尾,底部开始、中间和结尾。大家以后可以根据自己实际的业务需求去运用Box。