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.

120 lines
4.4 KiB

# Keyboard events handling
## Prerequisites
This tutorial expects set and ready Compose project build similar to which is described in [Getting Started tutorial](../Getting_Started)
## KeySets & ShortcutHandler
Compose for Desktop has a few utilities to work with shortcuts:
`KeysSet` represents a simultaneously pressed chord of keys. You can construct a `KeysSet` using Key's extension function:
``` kotlin
Key.CtrlLeft + Key.Enter
```
`ShortcutHandler` accepts `KeysSet` and returns a handler which could be used as a callback for `keyInputFilter`
## Event handlers
There are two different ways how you can handle key events in Compose for Desktop:
- By setting up an event handler based on a focused component
- By setting up an event handler in the scope of the window
## Focus related events
It's working in the same way as in Compose for Android, see for details [API Reference](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/key/package-summary#keyinputfilter)
The most common use case is to define keyboard handlers for active controls like `TextField`. Here is an example:
``` kotlin
import androidx.compose.desktop.Window
import androidx.compose.foundation.Text
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.*
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
@OptIn(ExperimentalKeyInput::class)
fun main() = Window(title = "Compose for Desktop", size = IntSize(300, 300)) {
MaterialTheme {
var consumedText by remember { mutableStateOf(0) }
var text by remember { mutableStateOf("") }
Column(Modifier.fillMaxSize(), Arrangement.spacedBy(5.dp)) {
Text("Consumed text: $consumedText")
TextField(
value = text,
onValueChange = { text = it },
modifier = Modifier.keyInputFilter(
ShortcutHandler(Key.CtrlLeft + Key.Enter) {
consumedText += text.length
text = ""
}
)
)
}
}
}
```
Note an annotation `@OptIn(ExperimentalKeyInput::class)`. Keyboard-related event handlers are a still-experimental feature of Compose and API changes are possible, so it requires it to use special annotation to emphasize the experimental nature of the code.
![keyInputFilter](keyInputFilter.gif)
## Window-scoped events
`AppWindow` instances have `keyboard` property. Using it, it's possible to define keyboard shortcuts that are always active for the current window. See an example:
``` kotlin
import androidx.compose.desktop.AppWindow
import androidx.compose.desktop.Window
import androidx.compose.foundation.Text
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.ExperimentalKeyInput
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalKeyInput::class)
fun main() = Window(title = "Compose for Desktop", size = IntSize(300, 300)) {
MaterialTheme {
Column(Modifier.fillMaxSize(), Arrangement.spacedBy(5.dp)) {
Button(
modifier = Modifier.padding(4.dp),
onClick = {
AppWindow(size = IntSize(200, 200)).also {
it.keyboard.shortcut(Key.Escape) {
it.close()
}
}.show {
Text("I'm popup!")
}
}
) {
Text("Open popup")
}
}
}
}
```
![window_keyboard](window_keyboard.gif)