今天大概会聊到的范围
- Constraint Layout in Compose
上一篇提到,有 Row / Column 和 Box,配合各种 alignment 的方式,就可以排出各种画面。事实上,原先的 Android 画面也是如此,透过 horizontal 和 vertical 的 LinearLayout 就可以排出各种画面。
但没多久,大家就发现问题了。画面的设计越来越复杂,越来越多层的 Layout 需要被互相嵌套,进而导致了效能问题。最後,为了摊平 view 的层数,RelativeLayout 和 ConstraintLayout 产生并被推荐变成画画面时的固定班底。
在 Compose 中,因为运算 layout 大小的路线不同,嵌套多层 Composable 并不会造成过多的运算压力,因此大家可以更放心的透过 Row / Column 这类基本的 Layout 进行布局。
但 ConstraintLayout 还是很有帮助的。透过描述 item 与 item 之间的关联,让这个 View 可以自适应各种内容与大小,有时是非常方便的。
所以,要如何在 Compose 中使用 ConstraintLayout 呢?
implementation "androidx.constraintlayout:constraintlayout-compose:$constraint_version"
ConstraintLayout 并不在 Compose 的 library 中,版本也是跟着 constraint layout 的版本。在使用之前要另外导入。
和 XML 不同,在 Compose 中每个 component 必没有 id 。因此,在形容 component 间的关系之前,必须得先替每个 component "命名"。
ConstraintLayout() {
// 建立用来做关联的 "id/ref"
val (titleRef, coverArtRef, blockSpaceRef) = createRefs()
}
透过 createRefs()
这个 funciton, 可以产出多个 "ref",功能和 XML 中的 id 类似。透过 destructuring 的方式可以一次定义出多个 ref。
接下来,在 ConstraintLayout 中的 Composable 的会多一个 constraintAs
的 Modifier 用来描述 constraint。用 constraintAs
时需要提供一个稍早产生出来的 ref,并且提供一个 Lambda,在 lambda 中描述这个 component 与其他 component 的关系。
Text(
text = "Text",
modifier = Modifier.constrainAs(titleRef) { // 使用 Modifier.constrainAs 定义每个元件的 id
// 在这里定义这个元件与其他元件的关联 (constraint)
// parent 是内建的
top.linkTo(parent.top, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
}
)
在描述时,可以透过 <top|bottom|start|end>.linkTo(<ref>.<top|bottom|start|end>)
的语法描述物件与物间之间的关系。
另外,也可以直接使用 linkTo
这个 function 一次描述垂直、水平或四周的 constraint
Spacer(modifier = Modifier
.constrainAs(blockSpaceRef) {
// linkTo function 可以一次定义多个 constraint
linkTo(top = parent.top, bottom = parent.bottom)
})
如此,就可以和使用熟悉的 ConstraintLayout 逻辑,来建构画面了
@Preview(
heightDp = 80,
widthDp = 160
)
@Composable
fun `Preview Constraint`(){
ConstraintLayout(
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.background(color = backgroundColor)
) {
// 建立用来做关联的 "id"
val (titleRef, coverArtRef, blockSpaceRef) = createRefs()
Text(
text = "Talking",
// 使用 Modifier.constrainAs 定义每个元件的 id
modifier = Modifier.constrainAs(titleRef) {
// 在这里定义这个元件与其他元件的关联 (constraint)
// parent 是内建的
top.linkTo(parent.top, margin = 8.dp)
start.linkTo(parent.start, margin = 8.dp)
},
color = Color.White, fontWeight = FontWeight.Black
)
Spacer(modifier = Modifier
.constrainAs(blockSpaceRef) {
// linkTo function 可以一次定义多个 constraint
linkTo(top = parent.top, bottom = parent.bottom)
}
.defaultMinSize(minHeight = 100.dp))
Image(
painter = painterResource(id = image),
contentDescription = null,
modifier = Modifier
.constrainAs(coverArtRef) {
bottom.linkTo(parent.bottom)
end.linkTo(parent.end, margin = (-10).dp)
}
.height(60.dp)
.width(60.dp)
.rotate(30f)
)
}
}
实际使用起来,发现 ConstraintLayout 在 Compose 的结构下依然简单易懂。很适合在画面关系复杂时使用。但仍要再次提醒,在 Compose 的结构下,ConstraintLayout 不再是因为效能的选择。在其他平台使用 Compose 时也不支援。但当画面关系复杂,不适合用简易的 Row / Column 描述时,ConstraintLayout 会是个增加程序可读性的好帮手。
Reference:
<<: Re: 新手让网页 act 起来: Day03 - 再次了解React.createElement()
在一般的软件公司,和面对规模的不大的专案,除非你是个对软件开发、工程品质、效率 “真的” 有兴趣,而...
找到一个有趣的程序码,改了一下,可截取Video画面,存成一张张图片。 进行中想要中断执行,可按 E...
在电脑世界中,很多编码都是复杂且看不懂的, 例如颜色编码,FF0000代表红色,800080代表绿色...
Stack(堆叠)是一种後进先出(LIFO)的资料结构 看一下图 注:图源 你可以想像一下在厨房洗碗...
普林演算法 紫色为可以选择的路线,绿色为走的路线 找可选择的最小值路线去走,就可以完成 克鲁斯克尔演...