在 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!")
}

除了直接把整個 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 = true 和 showSystemUi = true
showBackground = true:通常會加,雖然現在看不太出來差別,但後續要測 dark theme 應該就會有差?showSystemUi = true:通常不會加,因為 preview 就是要看某個特定的 UI 元件而已,要看整體的 Android 畫面就直接 build 到手機上就好在實作 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 來改。
另外 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 非常重要!!這是 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.background().padding() 和 Modifier.padding().background() 的結果其實是完全不一樣的,要小心!!!

所以在使用 modifier 時,最好還是多測試一下,才能達到自己想要的效果。
除了下面所列的常用設定之外,modifier 還有很多很多很多設定,族繁不及備載,建議有遇到時再查詢即可。
.size(100.dp):指定該元件的高度、寬度都為 100.dp.fillMaxSize():填滿上下左右的空間,撐到跟父元素一樣大.fillMaxWidth() 和 .fillMaxHeight(),適合用在只想撐滿上下、或是只想撐滿左右的情境
.padding(10.dp):控制邊界的距離
圖片來源: Android Developers Codelab: Add images to your Android app
.background(Color.Yellow):設定背景顏色.border(5.dp, Color.Red):設定邊框的粗細和顏色