2 - Jetpack Compose 介紹、@Composable、@Preview、modifier

古古

2025/12/30


@Composable:創建 UI 元件 #

在 Jetpack Compose 中,每一塊 UI 元件都是一個 Compose,所以就像是一棵很大的 UI tree 一樣,可以不斷的在裡面用其他的 UI 小元件,最終組成使用者看到的畫面。

圖片來源: Android Developers - Semantic Tree

舉例來說,可以在 Kotlin 中創建一個 function Greeting(),然後在裡面使用 Jetpack Compose 的基礎元件 Text,最後在這個 function 上面加上 @Composable,這個 function 就可以成為一個 UI 元件了!

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

不過要特別注意,這裡的 function 命名和一般 Kotlin 不同,Compose 元件的首字母一定要大寫!! 這是 Jetpack Compose 的默契,所以此處要寫成 Greeting(),而不是 greeting()

創建好 UI 元件 Greeting() 之後,就可以在 MainActivity 的 onCreate() 主入口使用這個 UI 元件。

可以把 setContent {} 視為 UI tree 的 root,他會將裡面的 UI 元件渲染在 Android 畫面上,所以就可以在 setContent {} 中 call 剛剛建好的 Greeting() 元件,最終就可以在畫面上呈現 “Hello Android” 的文字了!

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 重要!setContent 是一切 UI 畫面的源頭,只有放在裡面的 UI 元件才會呈現在 Android 畫面上
        setContent {
            MyApplicationTheme {
                // 使用剛剛創建好的 UI 元件 Greeting
                Greeting("Android")
            }
        }
    }
}

// 一個 UI 元件,記得 function 名稱的首字母要大寫!
@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

@Preview:預覽 UI 元件 #

除了直接把整個 Android 程式 build 到手機上之外,Android Studio 也提供另一個作法,讓我們能直接「預覽」某一個 compose UI 元件。

像是如果想要預覽上面的 Greeting 元件,就只要在 MainAcitivty 裡面再寫一個方法,並且在該方法上面加上 @Preview@Composable,就可以在這裡預覽任何 compose 元件。

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme {
        Greeting("Android")
    }
}

不過從這個 Preview 效果也可以看到,他和真實呈現在 Android 手機上的畫面還是有落差,畢竟這功能只是讓你快速讓你測試某個 UI 元件而已,最終會長什麼樣子還是要看 setContent {} 對整個 Android 畫面的渲染結果。但不得不說如果只是要測單一個小 UI 元件的話,用 Preview 來測是真的快👍。

另外在使用 @Preview 時,有兩個參數可以加,分別是 showBackground = trueshowSystemUi = true

  • showBackground = true:通常會加,雖然現在看不太出來差別,但後續要測 dark theme 應該就會有差?
  • showSystemUi = true:通常不會加,因為 preview 就是要看某個特定的 UI 元件而已,要看整體的 Android 畫面就直接 build 到手機上就好

modifier 修飾符 #

在實作 Jetpack Compose 的 UI 元件時,有一個超級萬用的參數 modifier,不管是要調整 padding(間距)、background(背景顏色)、border(邊框)…等等,全部都可以用 modifier 來設定。

像是在實作 Text 元件時,就可以用 modifier 來指定 padding 距離、順便也可以使用 modifier 來指定 background 背景顏色。

@Composable
fun Greeting(name: String) {
    Text(
        text = "Hello $name!",
        modifier = Modifier
            .background(Color.Cyan)  // 改變背景顏色為水藍色
            .padding(36.dp)  // padding 設為 36 dp
    )
}

所以將來不管是要改 padding 還是改 background,都可以直接透過 modifier 來改。

由外部的 caller 決定 modifier 的樣式 #

另外 modifier 在使用上還有一個很常見的用法,就是 「將 modifier 作為參數傳進 compose 元件裡面,讓外部的 caller 可以改變 compose 內部元件的樣式」

舉例來說,上面的 Greeting 元件可以改寫成下面這樣,並且習慣上會把 modifier 放在最後一個參數來傳遞。

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {  // 參數多傳 modifier
    Text(
        text = "Hello $name!",
        modifier = modifier  // 傳遞 modifier 參數給 Text 元件
    )
}

當改寫成上面這樣之後,Text 就會使用外部傳進來的 modifier 來決定樣式,所以當 Preview 改寫成下面這樣時,最終所呈現的效果就是 background 為黃色、且 padding 為 20 的 Hello Android。

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme {
        Greeting(
            name = "Android",
            modifier = Modifier
                .background(Color.Yellow)  // 改變背景顏色為黃色
                .padding(20.dp)   // padding 設為 20 dp
        )
    }
}

給 modifier 參數一個預設值 #

另外將 modifier 添加到參數時要注意一個細節,就是要寫成 modifier: Modifier = Modifier,最後面那個 = Modifier 非常重要!!這是 Kotlin 中給參數一個預設值的寫法。

所以當我們這樣寫之後,外部的 caller 愛給不給 modifier 都可以,如果有給 modifier 就用外部給的,如果沒給 modifier 就會得到一個空的 Modifier(即是沒有添加任何設定的樣式)。

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
   // ...
}

// 合法,Greeting 最終得到的是一個預設的空的 Modifier
Greeting(name = "Android")

// 也合法,Greeting 會得到一個已經設定好 background 為 yellow 的 modifier
Greeting(name = "Android", modifier = Modifier.background(Color.Yellow))

modifier 的順序很重要! #

在使用 modifier 時還有一個超級重要的地方要注意,就是「順序不能亂寫」!!!

modifier 的順序超級重要,順序不一樣造成的結果也不一樣,所以像是 Modifier.background().padding()Modifier.padding().background() 的結果其實是完全不一樣的,要小心!!!

所以在使用 modifier 時,最好還是多測試一下,才能達到自己想要的效果。

常用的 modifier 方法 #

除了下面所列的常用設定之外,modifier 還有很多很多很多設定,族繁不及備載,建議有遇到時再查詢即可。

大小控制 #

  • .size(100.dp):指定該元件的高度、寬度都為 100.dp
  • .fillMaxSize():填滿上下左右的空間,撐到跟父元素一樣大
    • 類似的還有 .fillMaxWidth().fillMaxHeight(),適合用在只想撐滿上下、或是只想撐滿左右的情境

邊界控制 #

  • .padding(10.dp):控制邊界的距離
    • 如果只傳一個參數 10.dp,那就是上下左右都是 10.dp,如果想要個別控制上下左右,可以用 top、bottom、start(左)、end(右)來控制,或是如果想要同時控制上下、左右的話,則可以用 vertical 和 horizontal 來控制
    • 圖片來源: Android Developers Codelab: Add images to your Android app

顏色控制 #

  • .background(Color.Yellow):設定背景顏色
  • .border(5.dp, Color.Red):設定邊框的粗細和顏色