###### tags: `android`, `compose`, `constraintLayout`
###### title: [Compose 系列 - 3] Compose UI - ConstraintLayout
# [Compose 系列 - 3] Compose UI - ConstraintLayout
[TOC]
## 前言
前面介紹了基本的 Layout:
- [[Compose 系列 - 1] UI - Layout Box & Modifier](/s23tCoUbQ_CN7c5_yNPMHQ)
- [[Compose 系列 - 2] UI - Layout Column/Row](/v4x18WsIRfCqCMSFkfQPLQ)
前面的Layout, 僅能提供間單的佈局位置. 而ConstraintLayout 提供 相對位置 / 百分比例 的方法進行佈局, 從而讓佈局更容易進行.
---
## Gradle
```kotlin=
val constraint_ver = "1.0.0-alpha07"
val compose_ver = "1.0.0-beta07"
dependencies {
...
implementation("androidx.constraintlayout:constraintlayout-compose:${constraint_ver}")
}
```
:::warning
:ghost:
由於還在 `alpha/beta` 階段
需注意其他相關的 `compose` 版本是否跑起來沒問題
自行斟酌版本號的使用
:::
## Usage
用法跟之前的Constraint 差不多:
> 1. 給定元件id
> 2. 設定上下左右, ...等關係
Ex:
假設我希望有一個`button`, 下方要有一個`text`. 除了使用`Column` 也可以用以下的方式
```kotlin=
@Composable
fun ConstraintLayoutContent() {
ConstraintLayout(modifier = Modifier.background(Color.Gray)) {
// 創造元件id
val (buttonId, textId) = createRefs()
Button(
onClick = { /* Do something */ },
// 透過 ConstraintLayoutScope 底下的 constrainAs(id)
// 指定該component id: buttonId
modifier = Modifier.constrainAs(buttonId) {
// 將 btn 上緣指定至 parent 上緣
// 並保持16.dp 距離
top.linkTo(parent.top, margin = 16.dp)
}
) {
Text("Button")
}
// 一樣將 textId 塞進 Text 元件
Text("Text", Modifier.background(Color.White).constrainAs(textId) {
// 將 text 上緣 指定至 btn 下緣, 並保持 16.dp 距離
top.linkTo(buttonId.bottom, margin = 16.dp)
// 將text 左右, 對齊 btn 左右
start.linkTo(buttonId.start)
end.linkTo(buttonId.end)
})
}
}
```

又或者透過ConstraintSet, 先進行關係的聯繫, 在賦予對應component id:
```kotlin=
@Composable
fun ConstraintWithConstraintSet() {
ConstraintLayout(
modifier = Modifier.background(Color.Gray),
constraintSet = ConstraintSet {
// 建立關係
val buttonId = createRefFor("btnId")
val textId = createRefFor("textId")
constrain(buttonId) {
top.linkTo(parent.top, 16.dp)
}
constrain(textId) {
top.linkTo(buttonId.bottom, margin = 16.dp)
start.linkTo(buttonId.start)
end.linkTo(buttonId.end)
}
}
) {
// 賦予 compontent id
Button(
onClick = { /* Do something */ },
modifier = Modifier.layoutId("btnId")
) {
Text(text = "Button")
}
Text("Text",
Modifier
.background(Color.White)
.layoutId("textId"))
}
}
```
畫面是長一樣的~
---
### GuideLine
使用者可以創建一條輔助線, 僅提供幫助進行建構畫面, 實際上在繪畫階段時並不會進行繪製.
`ConstraintLayoutBaseScope` 底下, 有`createGuidelineFromXXX()` 可以創建
Ex:
```kotlin=
@Composable
fun createGuide() {
ConstraintLayout {
val textId = createRefs()
// 創建 水平guideLine, 距離parent上緣20dp
val absTop = createGuidelineFromTop(20.dp)
// 創建 水平guideLine, 距離parent上緣20dp
val perTop = createGuidelineFromTop(0.4f)
Text("Text", Modifier.constrainAs(textId) {
top.linkTo(absTop)
}
}
}
```
---
### Barrier
類似於GuideLine 的效果, 差別在於他是可隨著條件進行變動的 GuideLine.
:::warning
:book: 詳細介紹可參考
[ConstraintLayout-Barrier 介紹](http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/1017/8601.html)
:::
用法同上, `createXXXBarrier()`
---
### Chains
直接上code:
```kotlin=
@Composable
fun ConstraintChain() {
ConstraintLayout(
modifier = Modifier.background(Color.Gray),
constraintSet = ConstraintSet {
val text1Id = createRefFor("text1")
val text2Id = createRefFor("text2")
val text3Id = createRefFor("text3")
createHorizontalChain(
text1Id,
text2Id,
text3Id,
chainStyle = ChainStyle.Spread
// ChainStyle 有三種預設模式:
// Spread: 平均分配空間, 左右留空白
// SpreadInside: 平均分配空間, 左右不留空白
// Packed: 元件互相緊連, 並 水平置中
// 而 Packed 可以放置bias 參數, 控制水平位移
)
}
) {
Text("test1", Modifier.layoutId("text1"))
Text("test2", Modifier.layoutId("text2"))
Text("test3", Modifier.layoutId("text3"))
}
}
```

## 小記
基本的佈局皆以介紹~
但我想大家應該會很好奇, `RecyclerLayout` / `ViewPager` / ... 其他常用的 Layout, 在compose 裡要怎麼用呢?
<div style="color:#f04c00;">因此, 下回介紹: compose 版本對應RecyclerView 的使用方法</div>
## 延伸閱讀
:::warning
:book:
- [Exploring Constraint Layout in JetPack Compose](https://medium.com/android-dev-hacks/exploring-constraint-layout-in-jetpack-compose-67b82123c28b)
- [ConstraintLayout-Barrier 介紹](http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/1017/8601.html)
:::
## 環境配置
- Android Studio Arctic Fox | 2020.3.1 Canary 15
:::spoiler
> Android Studio Arctic Fox | 2020.3.1 Canary 15
Build #AI-203.7717.56.2031.7321754, built on April 29, 2021
Runtime version: 11.0.10+0-b96-7281165 x86_64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 10.15.7
GC: G1 Young Generation, G1 Old Generation
Memory: 2048M
Cores: 8
Registry: external.system.auto.import.disabled=true
Non-Bundled Plugins: org.jetbrains.kotlin
:::
- compose version:`1.0.0-beta07`
- kotlin-gradle-plugin:`1.4.32`
- com.android.tools.build:gradle:`7.0.0-beta03`