在實作 Desktop App 時,有一種很特別的 UI 是 Tray
,也就是在功能列上的小圖示。許多 App 會把一些小工具收在 Tray
裡,方便使用者可以隨時取用,做為 Window
之外的延伸。甚至有些 App 根本就沒有 Window
,直接透過 Tray
上的選單跟使用者互動。Tray
元件是 Desktop 環境才有的設計,今天的耕讀筆記就來研究一下其用法及設定值。
Tray
元件我們要在應用程式一啟動的時候就宣告一個 Tray
元件,一般會直接宣告在 Window
元件之前,若 App 沒有 Window
的設計,也可以只宣告 Tray
即可。Tray
元件提供四個設定值來調整其外觀及行為:
fun main() = application {
val trayState = rememberTrayState()
Tray(
icon = painterResource("..."),
state = trayState,
tooltip = "MyApp Tray",
onAction = { /* ... */ }
) {
Menu(text = "File") {
Item(text = "Open", onClick = { /* ... */ })
}
Menu("Edit") {
Item(text = "Cut", onClick = { /* ... */ })
Item(text = "Copy", onClick = { /* ... */ })
Item(text = "Paste", onClick = { /* ... */ })
}
}
}
icon
:設定 Tray
在系統工具列上的圖示,支援傳入 Painter
實例。state
:紀錄 Tray
的狀態,並可用於發送 Notification
。tooltip
:設定 Tray
的工具列提示,當滑鼠停在圖示上約三秒時顯示。onAction
:當使用者以滑鼠點擊 Tray
時觸發的事件。在使用 Tray
時,需注意以下四點:
icon
參數如同我們熟悉的其他元件,可用 painterResource()
或向量繪製的方式傳入。state
預設是可以不用傳入的,但一般為了方便取出與修改,會自行宣告 val trayState = rememberTrayState()
後再傳入。onAction
事件在不同作業系統上的觸發條件是不同的,在 Windows 上是雙擊圖示、在 macOS 上是右鍵單擊圖示。Tray
有第五個參數 menu
,但因為 menu
接受 Function Parameter 且是最後一個參數,所以依 Kotlin 慣例可以直接放在 Lambda 裡。在上面的範例裡,因為要做出階層選單,所以用了 Menu
及 Item
兩種元件。若只有一層選單的話,可以只用 Item
元件實作。Tray
現階段的限制Compose for Desktop 雖然提供簡單易用的 Tray
元件,但現階段能做的功能仍很有限,官方僅示範功能選單的範例,若要做到市面上許多 Tray App 那種自訂樣式的視窗,只靠 @Composable
元件是做不到的,得自行呼叫底層的 Swing API 進行實作。