Tastaturaktionen verarbeiten

Wenn der Nutzer eine bearbeitbare Textkomponente wie ein TextField fokussiert und eine Hardwaretastatur an das Gerät angeschlossen ist, wird die gesamte Eingabe vom System verarbeitet. Sie können Tastenkombinationen bereitstellen, indem Sie Tastenereignisse verarbeiten.

Standard-Tastenkombinationen

Die folgenden Tastenkombinationen sind standardmäßig verfügbar.

Tastenkombination Aktion Composables, die die Verknüpfung unterstützen
Umschalttaste + Strg + Linkspfeil/Rechtspfeil Text bis zum Anfang/Ende des Wortes auswählen BasicTextField, TextField
Umschalttaste + Strg + Aufwärtspfeil/Abwärtspfeil Text bis zum Anfang/Ende des Absatzes auswählen BasicTextField, TextField
Umschalttaste + Alt + Aufwärtspfeil/Abwärtspfeil oder Umschalttaste + Meta + Linkspfeil/Rechtspfeil Text bis zum Anfang/Ende des Textes auswählen BasicTextField, TextField
Umschalttaste + Linkspfeil/Rechtspfeil Zeichen auswählen BasicTextField, TextField
Strg + A Alle auswählen BasicTextField, TextField
Strg + C/Strg + X/Strg + V Kopieren/Ausschneiden/Einfügen BasicTextField, TextField
Strg + Z/Strg + Umschalttaste + Z Rückgängig machen/Wiederholen BasicTextField, TextField
Bild ab/Bild auf Scrollen LazyColumn, der Modifikator verticalScroll, der Modifikator scrollable

Wichtige Ereignisse

In Compose können Sie einen einzelnen Tastendruck mit dem Modifikator onKeyEvent verarbeiten. Der Modifikator akzeptiert ein Lambda, das aufgerufen wird, wenn die modifizierte Komponente ein Schlüsselereignis empfängt. Ein Schlüsselereignis wird als KeyEvent-Objekt beschrieben. Sie können die Informationen zu jedem Schlüsselereignis abrufen, indem Sie auf das Objekt im Lambda verweisen, das an den Modifikator onKeyEvent übergeben wird.

Ein Tastendruck sendet zwei Schlüsselereignisse. Eines wird ausgelöst, wenn der Nutzer die Taste drückt, das andere, wenn die Taste losgelassen wird. Sie können die beiden Schlüsselereignisse anhand des Attributs type des Objekts KeyEvent unterscheiden.

Der Rückgabewert des Lambda-Ausdrucks onKeyEvent gibt an, ob das Schlüsselereignis verarbeitet wird oder nicht. Gib true zurück, wenn deine App das Tastenereignis verarbeitet, wodurch die Weitergabe des Ereignisses beendet wird.

Das folgende Snippet zeigt, wie eine doSomething()-Funktion aufgerufen wird, wenn der Nutzer die Taste S auf der Box-Komponente loslässt:

Box(
    modifier = Modifier
        .onKeyEvent {
            if (
                it.type == KeyEventType.KeyUp &&
                it.key == Key.S
            ) {
                doSomething()
                true
            } else {
                false
            }
        }
        .focusable()
) {
    Text("Press S key")
}

Modifikatortasten

Ein KeyEvent-Objekt hat die folgenden Attribute, die angeben, ob Modifikatortasten gedrückt sind oder nicht:

Beschreiben Sie die wichtigsten Ereignisse, die Ihre App verarbeitet, so genau wie möglich. Im folgenden Snippet wird eine doSomething()-Funktion nur aufgerufen, wenn der Nutzer die Taste S loslässt. Wenn der Nutzer eine Modifikatortaste wie die Umschalttaste drückt, ruft die App die Funktion nicht auf.

Box(
    modifier = Modifier
        .focusable()
        .onKeyEvent {
            if (
                it.type == KeyEventType.KeyUp &&
                it.key == Key.S &&
                !it.isAltPressed &&
                !it.isCtrlPressed &&
                !it.isMetaPressed &&
                !it.isShiftPressed
            ) {
                doSomething()
                true
            } else {
                false
            }
        }
) {
    Text("Press S key with a modifier key")
}

Click-Events für die Leertaste und die Eingabetaste

Die Leertaste und die Eingabetaste lösen ebenfalls Klickereignisse aus. Nutzer können beispielsweise die Medienwiedergabe mit der Leertaste oder der Eingabetaste umschalten (abspielen oder pausieren), indem sie Klickereignisse so verarbeiten:

MediaPlayer(modifier = Modifier.clickable { togglePausePlay() })

Der Modifikator clickable fängt Tastenereignisse ab und ruft den Callback onClick() auf, wenn die Leertaste oder die Eingabetaste gedrückt wird. Deshalb wird die Funktion togglePausePlay() im Snippet durch Drücken der Leertaste oder der Eingabetaste aufgerufen.

Nicht verbrauchte Schlüsselereignisse

Nicht verarbeitete Schlüsselereignisse werden von der Komponente, in der das Ereignis aufgetreten ist, an die umschließende äußere Komponente weitergegeben. Im folgenden Beispiel verarbeitet das InnerComponent Tastenereignisse, wenn die Taste S losgelassen wird. Daher empfängt das OuterComponent keine Tastenereignisse, die durch das Loslassen der Taste S ausgelöst werden. Deshalb wird die Funktion actionB() nie aufgerufen.

Andere Schlüsselereignisse auf InnerComponent, z. B. das Loslassen der Taste D, können von OuterComponent verarbeitet werden. Die Funktion actionC() wird aufgerufen, weil das Schlüsselereignis für das Loslassen der Taste D an das OuterComponent weitergegeben wird.

OuterComponent(
    modifier = Modifier.onKeyEvent {
        when {
            it.type == KeyEventType.KeyUp && it.key == Key.S -> {
                actionB() // This function is never called.
                true
            }

            it.type == KeyEventType.KeyUp && it.key == Key.D -> {
                actionC()
                true
            }

            else -> false
        }
    }
) {
    InnerComponent(
        modifier = Modifier.onKeyEvent {
            if (it.type == KeyEventType.KeyUp && it.key == Key.S) {
                actionA()
                true
            } else {
                false
            }
        }
    )
}

onKeyPreviewEvent-Modifikator

In einigen Anwendungsfällen möchten Sie ein Schlüsselereignis abfangen, bevor es die Standardaktion auslöst. Das Hinzufügen benutzerdefinierter Tastenkombinationen zu einer TextField ist ein typisches Beispiel. Mit dem folgenden Snippet können Nutzer durch Drücken der Tabulatortaste zur nächsten fokussierbaren Komponente wechseln.

val focusManager = LocalFocusManager.current
var textFieldValue by remember { mutableStateOf(TextFieldValue()) }

TextField(
    textFieldValue,
    onValueChange = {
        textFieldValue = it
    },
    modifier = Modifier.onPreviewKeyEvent {
        if (it.type == KeyEventType.KeyUp && it.key == Key.Tab) {
            focusManager.moveFocus(FocusDirection.Next)
            true
        } else {
            false
        }
    }
)

Standardmäßig fügt die Komponente TextField jedes Mal ein Tabulatorzeichen hinzu, wenn Nutzer die Tabulatortaste drücken, auch wenn das Tastenereignis mit dem Modifikator onKeyEvent verarbeitet wird. Wenn Sie den Tastaturfokus verschieben möchten, ohne Tabulatorzeichen hinzuzufügen, verarbeiten Sie das Schlüsselereignis, bevor Sie die mit dem Schlüsselereignis verknüpften Aktionen auslösen, wie im Snippet gezeigt. Der Lambda-Ausdruck onKeyPreviewEvent() fängt das Schlüsselereignis ab, indem er true zurückgibt.

Die übergeordnete Komponente kann das Schlüsselereignis abfangen, das auf ihren untergeordneten Komponenten auftritt. Im folgenden Snippet wird die Funktion previewSKey() aufgerufen, wenn Nutzer die Taste S drücken, anstatt die Funktion actionForPreview() aufzurufen.

Column(
    modifier = Modifier.onPreviewKeyEvent {
        if (it.key == Key.S) {
            previewSKey()
            true
        } else {
            false
        }
    }
) {
    Box(
        modifier = Modifier
            .focusable()
            .onPreviewKeyEvent {
                actionForPreview(it)
                false
            }
            .onKeyEvent {
                actionForKeyEvent(it)
                true
            }
    ) {
        Text("Press any key")
    }
}

Der onPreviewKeyEvent()-Lambda-Ausdruck für die Box-Komponente wird auch nicht ausgelöst, wenn Nutzer die Tabulatortaste drücken. Der Lambda-Ausdruck onPreviewKeyEvent() wird zuerst für die übergeordnete Komponente aufgerufen, dann wird onPreviewKeyEvent() in der untergeordneten Komponente aufgerufen. Dieses Verhalten können Sie nutzen, um bildschirmweite Tastenkombinationen zu implementieren.

Zusätzliche Ressourcen