在與使用者互動的元件裡,Button 佔了很大的比重,用途也很廣泛。今天的耕讀筆記,就來綜覽一下 Compose 提供的 Button 元件,了解這系列的元件各自是在哪些情境下使用。
Button 元件在 Compose 的設計裡,Button 只是一個可以回應 onClick 事件的容器,本身其實沒有任何 UI。因此在使用 Button 元件時,至少需要傳入 onClick 及 content 兩個參數。
Button(onClick = { /* ... */ }) {
    Text("Submit")
}
content 參數接受一個函式參數,且是最後一個參數,在 Kotlin 的語法設計裡,可以直接放在小括號(())的後面,以大括號({})包夾住 Button 的 UI,比方說一個 Text 元件。
Button UI因為 Button 需要自行實作 UI,所以開發者可以依照需求做出任何樣式的的按鈕,比方說在按鈕上放置兩種不同顏色的文字。
Button(onClick = {/* ... */}) {
    Text(text = "Click ", color = Color.Magenta)
    Text(text = "Here", color = Color.Green)
}
甚至要在 Button 裡放圖片也是可以的:
Button(onClick = { /* ... */ }) {
    Image(
        painterResource("..."),
        contentDescription = "...",
    )
    Text("...")
}
Button 背景顏色預設 Button 的背景顏色是使用 Material Design 的設計,若要修改的話,可以透過 colors 參數調整。
Button(
    onClick = { /* ... */ },
    colors = ButtonDefaults.buttonColors(backgroundColor = Color.DarkGray)
) {
    Text(text = "...",color = Color.White)
}
Button 邊框Button 元件也提供 border 參數讓開發者可以設定邊框的樣式,透過 BorderStroke 實例設定筆刷寬度及顏色,就可以讓按鈕有不同顏色的邊框。
Button(
    onClick = { /* ... */ },
    border = BorderStroke(2.dp, Color.Red),
    colors = ButtonDefaults.buttonColors(backgroundColor = Color.White)
) {
    Text(text = "...", color = Color.DarkGray)
}
Button 形狀預設的 Button 形狀是採圓角矩形,若想要以其他造型呈現,在 Compose 裡也是可行的,只要傳入想要的造型至 shape 參數即可:
// 矩形
Button(
    onClick = { /* ... */ },
    shape = RectangleShape
) {
    Text(text = "...")
}
// 設定圓角矩形到呈橢圓形
Button(
    onClick = { /* ... */ },
    shape = RoundedCornerShape(20.dp)
) {
    Text("..")
}
// 尖角矩形
Button(
    onClick = { /* ... */ },
    shape = CutCornerShape(50)
) {
    Text("...")
}
範例裡的 RoundedCornerShape 及 CutCornerShape 支援三種設定邊角的單位:
size: Dp
size: Float
percent: Int
Button 海拔(elevation)預設的 Button 在視覺上看起來像是放在一個平面,當滑鼠碰到它時,會在下方出現下落式陰影(Drop Shadow),在視覺上就像是「浮」起來的感覺,若想要調整這個預設的高度及視覺效果,可以透過調整 elevation 參數達成:
Button(
    onClick = { },
    elevation = ButtonDefaults.elevation(
        defaultElevation = 10.dp,
        pressedElevation = 15.dp,
        disabledElevation = 0.dp
    )
) {
    Text(text = "...")
}
Button 的狀態樣式Button 有一個 interactionSource 參數,可以用來監聽元件狀態的事件來源,透過它就可以根據元件狀態設定不同的樣式:
val interactionSource = remember { MutableInteractionSource() }
val pressState = interactionSource.collectIsPressedAsState()
val borderColor = if (pressState.value) Color.Green else Color.White
Button(
    onClick = { },
    border = BorderStroke(2.dp, color = borderColor),
    interactionSource = interactionSource,
) {
    Text(text = "Long Press")
}
在上面的例子裡,原本按鈕的邊框是白色,當按鈕處於被按下狀態時,邊框就會變成綠色。MutableInteractionSource 可以提供三種狀態的事件供監聽:
collectIsPressedAsState:判斷按鈕是否處於被按下的狀態。collectIsFocusedAsState:判斷按鈕是否正處理焦點的狀態。collectIsDraggedAsState:判斷按鈕是否處理被拖曳的狀態。Button 元件Compose 其實還提供各類 Button 元件供開發者使用,不過這些元件其實都只是 Button 元件加上預設樣式,省下開發者客製化的時間,在這邊也一併筆記各元件的特色及使用方式:
OutlinedButton 元件有別於 Button 預設是填滿顏色的按鈕,OutlinedButton 則是內部無填色、以外框線製作的按鈕,其餘樣式與 Button 無差異,若想要不同顯示樣式的按鈕,就可以用 OutlinedButton。
OutlinedButton(onClick = { /* ... */ }) {
    Text("...")
}
TextButton 元件TextButton 如同其名,顯示起來就像是文字一樣,不過當滑鼠碰面文字時,會有跟 Button 一樣的反白與點擊效果,若想要比較簡單的樣式、完全以文字為主的按鈕,就可以使用 TextButton。
TextButton(onClick = { /* ... */ }) {
    Text("...")
}
IconButton 元件IconButton 則是將圖示做為按鈕,預設顯示起來就是一個圓形的按鈕,圖示可以放入 Icons 類別裡各種預設好的圖案,也可以依需求設定成指定的圖片。
IconButton(onClick = { /* ... */ }) {
Icon(
    imageVector = Icons.Filled.Favorite,
    contentDescription = "..."
)
IconToggleButton 元件IconToggleButton 在外顯上跟 IconButton 是一樣的,只是多了一個 checked 屬性,用來記錄按鈕是否被點選的狀態,利用這個屬性來設定按鈕的外觀如圖示、顏色等,就可以做出開關型的按鈕。
val locked = remember { mutableStateOf(false) }
IconToggleButton(
    checked = locked.value,
    onCheckedChange = {
        locked.value = !locked.value
    },
) {
    Icon(
        imageVector = if (locked.value) { Icons.Filled.Lock } else { Icons.Outlined.Lock },
        contentDescription = "Lock",
        tint = if (locked.value) { Color.Red } else { Color.Green }
    )
}
在上面的例子裡,若按鈕被按下,則顯示為紅色實心鎖頭,反之則顯示為綠色外框的鎖頭。
FloatingActionButton 元件FloatingActionButton 是從 Mobile 直接移植過來的按鈕型式,其特色就是浮動於 UI 的右下角,通常用於新增或建立型的功能。在 Web UI 裡,比較常用於 Go to top(回到頁尾)的功能。
FloatingActionButton(
    onClick = { /* ... */ },
) {
    Icon(
        imageVector = Icons.Filled.Add,
        contentDescription = "..."
    )
}
在上例裡,將一個 Icon 設定為 FloatingActionButton 的 UI,將程式運行起來後,會看到按鈕的 Elevation 高於其他 UI 元件。
ExtendedFloatingActionButton 元件ExtendedFloatingActionButton 做為 FloatingActionButton 的延伸,只是用 text 及 icon 兩個參數預先組合出一圖示、文字搭配的浮動按鈕。
ExtendedFloatingActionButton(
    onClick = { /* ... */ },
    text = {
        Text(text = "...")
    },
    icon = {
        Icon(
            imageVector = Icons.Filled.Add,
            contentDescription = "...",
        )
    }
)
在看完這麼多 Button 後,讀者是不是也跟筆者一樣驚訝於 Compose 提供的豐富按鈕元件呢?下次在實作 UI 時,多看一下文件,可以少寫很多程式碼喔!