Try   HackMD
tags: android, compose, functional programming
title: [Compose 系列 - 1] UI - Layout Box & Modifier

[Compose 系列 - 1] UI - Layout Box & Modifier

主旨

構築畫面, 需要兩種 UI種類:

  1. 責顯示畫面的 View
  2. 負責佈局的 ViewGroup.

此篇以ViewGroup 的部分進行介紹:

在Compose 的世界裡, 如何進行畫面的佈局

Compose Layout

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
參考自:
Compose-Layout 官網介紹

基本的 Layout 為上述三種:

  1. Column: 垂直排列
  2. Row: 水平排列
  3. Box: 區域內放置 (想不太出來中文的解釋)

我們就從最簡單的 Box 來開始介紹, 關於Layout 的這檔事

Box

其實他就是相對應的 FragmentLayout. 因此他能做的事情非常簡單,
就是將Box 底下的畫面, 擺放在八個方位: 上下左右 和 四角落

@Composable fun BoxSample() { Box { // BoxScope Text("Hello World") } }

預設是出現在左上角

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

若想更改位置, 比如我想將文字至正上方, 此時需使用Modifier

@Composable fun BoxSample() { Box { // BoxScope Text( modifier = Modifier.align(Alignment.TopCenter), text = "Hello World" ) } }

Modifier 是什麼?

我個人的解釋是: 對 UI 進行通用的操作

  1. 他可以設定大小, 背景, clickEvent, padding, shadow, clip, 等 操作.
  2. 在特別的Scope 下, 可以進行特有的 動作

Common

先來解釋第一點:

@Composable fun BoxSample() { Box(modifier = Modifier .height(40.dp) // 固定高度 40 dp .wrapContentWidth() // android:layout_width:wrapContent .padding(10.dp) // padding 10 dp .background(color = Color.Red) .clickable { Log.d("log", "box click") } ) { // BoxScope Text(text = "Hello World") } }

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

簡單明瞭.

而操作的順序也是有差的! 比如我將 line: 6, 7 對調:

@Composable fun BoxSample() { Box(modifier = Modifier .height(40.dp) // 固定高度 40 dp .wrapContentWidth() // android:layout_width:wrapContent .background(color = Color.Red) .padding(10.dp) // padding 10 dp .clickable { Log.d("log", "box click") } ) { // BoxScope Text(text = "Hello World") } }

就會變成

  1. render backgroud
  2. padding 10dp

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

甚至還能進行多次的padding操作:

@Composable fun BoxSample() { Box(modifier = Modifier .height(40.dp) // 固定高度 .wrapContentWidth() // android:layout_width:wrapContent .padding(5.dp) .background(color = Color.Red) .padding(5.dp) .clickable { Log.d("log", "box click") } ) { // BoxScope Text(text = "Hello World") } }
  1. padding 5dp
  2. render background
  3. padding 5dp

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

更多操作大家可以去看API 文件


Special Scope

關於第二點, 眼尖的各位應該有發現前面的例子上我有註解 // BoxScope 的字樣, 在IDE 上應該也會看到提示. 實際上這個lambda 是有傳進一個 BoxScope 的 interface. 而在 BoxScope內, 可以執行 屬於Box 的操作. 比如剛剛講的例子:

@Composable fun BoxSample() { Box { // BoxScope Text( modifier = Modifier.align(Alignment.TopCenter), text = "Hello World" ) } }

Modifier.align(alignment: Alignment) 是只有在Box 底下可以執行的操作, 而上述例子相當於以前的 android:layout_gravity="top|center_horizontal"

Next

繼續講述, 關於Column 跟 Row 的操作, 基本上跟 也是跟原有的LinearLayout 不會相差太遠.

環境配置

  • 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