You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
7.8 KiB

# Mouse events
## What is covered
In this tutorial we will see how to install mouse event listeners on components
in Compose for Desktop.
## Mouse event listeners
4 years ago
### Click listeners
Click listeners are available in both Compose on Android and Compose for Desktop,
so code like this will work on both platforms:
4 years ago
```kotlin
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
3 years ago
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
3 years ago
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.sp
3 years ago
import androidx.compose.ui.window.singleWindowApplication
3 years ago
fun main() = singleWindowApplication {
var count by remember { mutableStateOf(0) }
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth()) {
var text by remember { mutableStateOf("Click magenta box!") }
Column {
@OptIn(ExperimentalFoundationApi::class)
Box(
modifier = Modifier
.background(Color.Magenta)
.fillMaxWidth(0.7f)
.fillMaxHeight(0.2f)
.combinedClickable(
onClick = {
text = "Click! ${count++}"
},
onDoubleClick = {
text = "Double click! ${count++}"
},
onLongClick = {
text = "Long click! ${count++}"
}
)
)
Text(text = text, fontSize = 40.sp)
}
4 years ago
}
}
```
<img alt="Application running" src="mouse_click.gif" height="500" />
4 years ago
### Mouse move listeners
As typically mouse and other positional pointers are only available on desktop platforms,
the following code will only work with Compose for Desktop.
Let's create a window and install a pointer move filter on it that changes the background
color according to the mouse pointer position:
4 years ago
```kotlin
import androidx.compose.foundation.background
3 years ago
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.getValue
4 years ago
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
3 years ago
import androidx.compose.runtime.setValue
4 years ago
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
4 years ago
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerMoveFilter
3 years ago
import androidx.compose.ui.window.singleWindowApplication
@OptIn(ExperimentalComposeUiApi::class)
3 years ago
fun main() = singleWindowApplication {
var color by remember { mutableStateOf(Color(0, 0, 0)) }
4 years ago
Box(
modifier = Modifier
.wrapContentSize(Alignment.Center)
.fillMaxSize()
.background(color = color)
.pointerMoveFilter(
onMove = {
color = Color(it.x.toInt() % 256, it.y.toInt() % 256, 0)
false
}
)
)
}
4 years ago
```
<img alt="Application running" src="mouse_move.gif" height="519" />
4 years ago
### Mouse enter listeners
Compose for Desktop also supports pointer enter and exit handlers, like this:
```kotlin
import androidx.compose.foundation.background
3 years ago
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Text
import androidx.compose.runtime.getValue
4 years ago
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
3 years ago
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
4 years ago
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerMoveFilter
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
3 years ago
import androidx.compose.ui.window.singleWindowApplication
4 years ago
@OptIn(ExperimentalComposeUiApi::class)
3 years ago
fun main() = singleWindowApplication {
Column(
Modifier.background(Color.White),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
4 years ago
repeat(10) { index ->
var active by remember { mutableStateOf(false) }
4 years ago
Text(
modifier = Modifier
.fillMaxWidth()
.background(color = if (active) Color.Green else Color.White)
.pointerMoveFilter(
onEnter = {
active = true
false
},
onExit = {
active = false
false
}
),
fontSize = 30.sp,
fontStyle = if (active) FontStyle.Italic else FontStyle.Normal,
text = "Item $index"
)
4 years ago
}
}
}
```
<img alt="Application running" src="mouse_enter.gif" height="500" />
### Mouse right/middle clicks and keyboard modifiers
Compose for Desktop contains desktop-only `Modifier.mouseClickable`, where data about pressed mouse buttons and keyboard modifiers is available. This is an experimental API, which means that it's likely to be changed before release.
```kotlin
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.mouseClickable
import androidx.compose.material.Text
3 years ago
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
3 years ago
import androidx.compose.ui.input.pointer.isAltPressed
import androidx.compose.ui.input.pointer.isCtrlPressed
import androidx.compose.ui.input.pointer.isMetaPressed
import androidx.compose.ui.input.pointer.isPrimaryPressed
import androidx.compose.ui.input.pointer.isSecondaryPressed
import androidx.compose.ui.input.pointer.isShiftPressed
import androidx.compose.ui.input.pointer.isTertiaryPressed
3 years ago
import androidx.compose.ui.window.singleWindowApplication
@OptIn(ExperimentalFoundationApi::class)
3 years ago
fun main() = singleWindowApplication {
var clickableText by remember { mutableStateOf("Click me!") }
Text(
modifier = Modifier.mouseClickable(
onClick = {
clickableText = buildString {
append("Buttons pressed:\n")
append("primary: ${buttons.isPrimaryPressed}\t")
append("secondary: ${buttons.isSecondaryPressed}\t")
append("tertiary: ${buttons.isTertiaryPressed}\t")
append("\n\nKeyboard modifiers pressed:\n")
append("alt: ${keyboardModifiers.isAltPressed}\t")
append("ctrl: ${keyboardModifiers.isCtrlPressed}\t")
append("meta: ${keyboardModifiers.isMetaPressed}\t")
append("shift: ${keyboardModifiers.isShiftPressed}\t")
}
}
),
text = clickableText
)
}
```
<img alt="Application running" src="mouse_event.gif" height="500" />
If you need more information about events there is an available raw AWT mouse event object in `mouseEvent` property of `PointerEvent`