對使用者的行為產生反應是 UI 很重要的功能之一,因此事件系統的豐富度與完整度就變成評估一個 UI 框架很重要的因子之一。在 Compose for Desktop 的世界裡,開發者可以透過兩種方式監聽元件的事件:
Modifier
註冊如 clickable
事件來擴充。以上兩種事件只在註冊的位置有些微差異外,在 Event Handler 是沒有差異的。而畢竟 Compose for Desktop 是為 Desktop 環境而設計的,因此今天討論的事件也會以 Desktop 環境的事件為主,也就是滑鼠、鍵盤事件。
之前的筆記是透過 Modifier
註冊 clickable
來取得滑鼠點擊的動作,但滑鼠點擊還可以分很多種行為,比方說:
假如想要註冊這些事件的話,可以用 Modifier
的 combinedClickable
來註冊 onClick
、onDoubleClick
、onLongClick
等三種不同的事件,每個事件都可傳入一個 Event Handler 來分別設定事件發生時要做的動作。
var eventName by remember { mutableStateOf("none") }
Text(
text = "Event: $eventName",
fontSize = 40.sp,
)
Box(
modifier = Modifier.background(Color.Gray)
.width(300.dp)
.height(100.dp)
.combinedClickable(
onClick = {
eventName = "Click!"
},
onDoubleClick = {
eventName = "DoubleClick!"
},
onLongClick = {
eventName = "LongClick!"
}
)
)
在上面的例子裡,當滑鼠對 Box
做出不同的點擊行為時,上方的 TextField
就會顯示收到的事件名稱,透過這個簡單的程式,就可以測試滑鼠的三種點擊事件。
除了點擊事件外,滑鼠還有許多事件可以註冊,比方說滑鼠移動(Move
)。
var color by remember { mutableStateOf(Color(0, 0, 0)) }
Box(
modifier = Modifier.wrapContentSize(Alignment.Center)
.fillMaxSize()
.background(color = color)
.onPointerEvent(PointerEventType.Move) {
val position = it.changes.first().position
color = Color(
position.x.toInt() % 256,
position.y.toInt() % 256,
0
)
}
)
在上面的例子裡,先註冊 onPointerEvent
,透過 PointerEventType.Move
指定監聽的事件類型為滑鼠移動,在 Event Handler 裡可以拿到 PointerEvent
,取出滑鼠在畫面上的座標值,再用座標值來改變 Box
的背景顏色,就可以做出有趣的互動效果。
若想監聽滑鼠移入(Enter
)和移出(Exit
)元件的事件,可以在註冊 onPointerEvent
時指定 PointerEventType.Enter
及 PointerEventType.Exit
事件類型。在下面的例子裡,原本畫面正中央的 Text
在滑鼠移入時會放大變紅字,滑鼠移出時會回復原狀。
var fontSize by remember { mutableStateOf(40.sp) }
var fontColor by remember { mutableStateOf(Color.Black) }
Text(
text = "Hover Here",
fontSize = fontSize,
color = fontColor,
modifier = Modifier.onPointerEvent(
PointerEventType.Enter
) {
fontSize = 100.sp
fontColor = Color.Red
}.onPointerEvent(
PointerEventType.Exit
) {
fontSize = 40.sp
fontColor = Color.Black
},
)
若使用有滾輪的滑鼠(也支援觸控版)的話,還可以監聽滾動事件(在觸控版上通常是雙指滑動),在註冊 onPointerEvent
時指定 PointerEventType.Scroll
事件類型即可。
var scale by remember { mutableStateOf(0f) }
Box(
modifier = Modifier.fillMaxSize()
.onPointerEvent(
PointerEventType.Scroll
) {
scale += it.changes.first().scrollDelta.y
},
contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier.size(10.dp)
.scale(scale)
.background(Color.Gray)
)
}
在上面的例子裡,畫面正中央的 Box
會依照滾動的 Y 軸放大縮小。