mirror of
https://github.com/jlengrand/compose-multiplatform.git
synced 2026-03-10 08:11:20 +00:00
Keyboard tutorial
This commit is contained in:
BIN
tutorials/Keyboard/keyInputFilter.gif
Normal file
BIN
tutorials/Keyboard/keyInputFilter.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
119
tutorials/Keyboard/main.md
Normal file
119
tutorials/Keyboard/main.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
BIN
tutorials/Keyboard/window_keyboard.gif
Normal file
BIN
tutorials/Keyboard/window_keyboard.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 486 KiB |
Reference in New Issue
Block a user