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
120 lines
4.4 KiB
4 years ago
|
# 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)
|