###### 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) }) } } ``` ![](https://i.imgur.com/J1u94G3.png) 又或者透過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")) } } ``` ![](https://i.imgur.com/tve43gZ.png) ## 小記 基本的佈局皆以介紹~ 但我想大家應該會很好奇, `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`