changed 4 years ago
Published Linked with GitHub
tags: android, compose, constraintLayout
title: [Compose 系列 - 3] Compose UI - ConstraintLayout

[Compose 系列 - 3] Compose UI - ConstraintLayout

前言

前面介紹了基本的 Layout:

前面的Layout, 僅能提供間單的佈局位置. 而ConstraintLayout 提供 相對位置 / 百分比例 的方法進行佈局, 從而讓佈局更容易進行.


Gradle

val constraint_ver = "1.0.0-alpha07" val compose_ver = "1.0.0-beta07" dependencies { ... implementation("androidx.constraintlayout:constraintlayout-compose:${constraint_ver}") }

:ghost:
由於還在 alpha/beta 階段
需注意其他相關的 compose 版本是否跑起來沒問題
自行斟酌版本號的使用

Usage

用法跟之前的Constraint 差不多:

  1. 給定元件id
  2. 設定上下左右, 等關係

Ex:
假設我希望有一個button, 下方要有一個text. 除了使用Column 也可以用以下的方式

@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:

@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:

@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.

:book: 詳細介紹可參考
ConstraintLayout-Barrier 介紹

用法同上, createXXXBarrier()


Chains

直接上code:

@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 裡要怎麼用呢?

因此, 下回介紹: compose 版本對應RecyclerView 的使用方法

延伸閱讀

環境配置

  • Android Studio Arctic Fox | 2020.3.1 Canary 15

    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
Select a repo