Kotlin Compose 05 鼠标事件

文章目录

Click listeners

示例就是点击会变色,根据是单击双击还是长按,分别修改RGB值。

 1package top.kikt.examples.event.mouse
 2
 3import androidx.compose.foundation.ExperimentalFoundationApi
 4import androidx.compose.foundation.background
 5import androidx.compose.foundation.combinedClickable
 6import androidx.compose.foundation.layout.Box
 7import androidx.compose.foundation.layout.Column
 8import androidx.compose.foundation.layout.padding
 9import androidx.compose.foundation.layout.size
10import androidx.compose.material.Text
11import androidx.compose.runtime.*
12import androidx.compose.ui.Modifier
13import androidx.compose.ui.graphics.Color
14import androidx.compose.ui.unit.dp
15
16@OptIn(ExperimentalFoundationApi::class)
17@Composable
18fun MouseEventExample() {
19    var redColor by remember { mutableStateOf(0) }
20    var greenColor by remember { mutableStateOf(0) }
21    var blueColor by remember { mutableStateOf(0) }
22
23    var lastEvent by remember { mutableStateOf("") }
24
25    val color = Color(redColor, greenColor, blueColor)
26    val textColor = if (redColor + greenColor + blueColor > 128 * 3) Color.Black else Color.White
27    Box(
28        modifier = Modifier
29            .background(color = color)
30            .size(300.dp, 300.dp)
31            .combinedClickable(
32                onClick = {
33                    redColor = (redColor + 32) % 256
34                    lastEvent = "onClick"
35                },
36                onDoubleClick = {
37                    greenColor = (greenColor + 32) % 256
38                    lastEvent = "onDoubleClick"
39                },
40                onLongClick = {
41                    blueColor = (blueColor + 32) % 256
42                    lastEvent = "onLongClick"
43                }
44            )
45            .padding(16.dp)
46    ) {
47        Column {
48            Text("The color rgb is ($redColor, $greenColor, $blueColor)", color = textColor)
49            Text("Last event is $lastEvent", color = textColor)
50        }
51    }
52}

combinedClickable 有一个问题,只支持鼠标左键,如果是右键,就不会触发事件。

Mouse move listeners

核心代码如下,其实就是添加了一个事件,在鼠标移动的时候,就会触发,效果是改变背景颜色

 1.onPointerEvent(PointerEventType.Move) { event ->
 2    val position = event.changes.first().position
 3    val changed = position.x != lastMoveOffset.x || position.y != lastMoveOffset.y
 4
 5    if (changed) {
 6        lastMoveOffset = position
 7        lastEvent = "onPointerEvent Move"
 8        redColor = (redColor + 1) % 256
 9        greenColor = (greenColor + 1) % 256
10        blueColor = (blueColor + 1) % 256
11    }
12}

Mouse enter and exit listeners

核心代码如下,其实就是添加了一个事件,在鼠标进入和离开的时候,就会触发,效果是改变背景颜色

 1@OptIn(ExperimentalComposeUiApi::class)
 2@Composable
 3private fun MouseEnterExample() {
 4    Column {
 5        repeat(10) { index ->
 6            var isEnter by remember { mutableStateOf(false) }
 7            Box(
 8                Modifier
 9                    .size(100.dp, 40.dp)
10                    .background(if (isEnter) Color.Red else Color.Green)
11                    .onPointerEvent(PointerEventType.Enter) {
12                        isEnter = it.type == PointerEventType.Enter
13                    }
14                    .onPointerEvent(PointerEventType.Exit) {
15                        isEnter = it.type == PointerEventType.Enter
16                    }
17            ) {
18                Text("index: $index")
19            }
20        }
21    }
22}

Mouse scroll listeners

核心代码如下,其实就是添加了一个事件,在鼠标滚动的时候,就会触发,效果是改变背景颜色

 1@OptIn(ExperimentalComposeUiApi::class)
 2@Composable
 3private fun MouseScrollExample() {
 4    var scroll by remember { mutableStateOf(0f) }
 5    Box(
 6        Modifier
 7            .fillMaxWidth()
 8            .height(200.dp)
 9            .background(Color.LightGray)
10            .onPointerEvent(PointerEventType.Scroll) {
11                scroll += it.changes.first().scrollDelta.y
12            }
13    ) {
14        Text("Scroll y: $scroll")
15    }
16}

Mouse pointer listeners

 1@ExperimentalComposeUiApi
 2private fun Modifier.onAllPointerEvent(
 3    eventTypeList: List<PointerEventType> = listOf(
 4        PointerEventType.Enter,
 5        PointerEventType.Exit,
 6        PointerEventType.Move,
 7        PointerEventType.Unknown,
 8        PointerEventType.Press,
 9        PointerEventType.Release,
10        PointerEventType.Scroll,
11    ),
12    pass: List<PointerEventPass> = listOf(PointerEventPass.Initial, PointerEventPass.Main, PointerEventPass.Final),
13    onEvent: (PointerEventType, PointerEventPass, PointerEvent) -> Unit
14): Modifier {
15    var modifier = this
16    for (pointerEventType in eventTypeList) {
17        for (pointerEventPass in pass) {
18            modifier = modifier.onPointerEvent(pointerEventType, pointerEventPass) {
19                onEvent(pointerEventType, pointerEventPass, it)
20            }
21        }
22    }
23    return modifier
24}
25
26@OptIn(ExperimentalComposeUiApi::class)
27@Composable
28private fun AwtEventExample() {
29    var text by remember { mutableStateOf("") }
30    Box(
31        modifier = Modifier
32            .fillMaxSize()
33            .padding(10.dp)
34            .background(Color.White)
35            .onAllPointerEvent { type, pass, event ->
36                val textList = ArrayList<String>()
37                textList.add("type: $type")
38                textList.add("pass: $pass")
39                textList.add("event: $event")
40                val awtEvent = event.awtEventOrNull
41                if (awtEvent != null) {
42                    textList.add("awtEvent: $awtEvent")
43                }
44                text = textList.joinToString("\n")
45            }
46    ) {
47        Text(text = text)
48    }
49}

pointerInput

这个方法是订阅式的接收指针事件,一个实验性方法

 1@Composable
 2private fun InputEventExample() {
 3    val list = remember { mutableStateListOf<String>() }
 4
 5    Column(
 6        Modifier
 7            .fillMaxSize()
 8            .pointerInput(Unit) {
 9                awaitPointerEventScope {
10                    while (true) {
11                        val event = awaitPointerEvent()
12                        val position = event.changes.first().position
13                        if (event.type != PointerEventType.Move) {
14                            list.add(0, "${event.type} $position")
15                        }
16                    }
17                }
18            },
19    ) {
20        for (item in list.take(20)) {
21            Text(item)
22        }
23    }
24}