Obsługa działań na klawiaturze

Gdy użytkownik skupi się na komponencie tekstowym możliwym do edytowania, np. TextField, a do urządzenia jest podłączona klawiatura sprzętowa, wszystkie dane wejściowe są obsługiwane przez system. Skróty klawiszowe możesz udostępniać, obsługując kluczowe zdarzenia.

Domyślne skróty klawiszowe

Te skróty klawiszowe są dostępne od razu.

Skrót klawiszowy Działanie Komponowalne funkcje obsługujące skrót
Shift+Ctrl+Strzałka w lewo/Strzałka w prawo Zaznacz tekst do początku/końca słowa BasicTextField, TextField
Shift+Ctrl+Strzałka w górę/Strzałka w dół Zaznacz tekst do początku/końca akapitu BasicTextField, TextField
Shift+Alt+Strzałka w górę/Strzałka w dół lub Shift+Meta+Strzałka w lewo/Strzałka w prawo Zaznacz tekst do początku/końca tekstu BasicTextField, TextField
Shift+Strzałka w lewo/Strzałka w prawo Wybierz znaki BasicTextField, TextField
Ctrl+A Zaznacz wszystko BasicTextField, TextField
Ctrl+C/Ctrl+X/Ctrl+V Kopiuj/wytnij/wklej BasicTextField, TextField
Ctrl+Z/Ctrl+Shift+Z Cofnij/ponów BasicTextField, TextField
PageDown/PageUp Przewiń LazyColumn, modyfikator verticalScroll, modyfikator scrollable

Kluczowe zdarzenia

W Compose możesz obsługiwać pojedyncze naciśnięcia klawiszy za pomocą onKeyEvent modyfikatora. Modyfikator akceptuje lambdę, która jest wywoływana, gdy zmodyfikowany komponent otrzyma kluczowe zdarzenie. Kluczowe zdarzenie jest opisywane jako KeyEvent obiekt. Informacje o każdym kluczowym zdarzeniu możesz uzyskać, odwołując się do obiektu w lambdzie przekazanej do modyfikatora onKeyEvent.

Naciśnięcie klawisza wysyła 2 kluczowe zdarzenia. Jedno jest wywoływane, gdy użytkownik naciśnie klawisz, a drugie – gdy go zwolni. Możesz odróżnić te 2 kluczowe zdarzenia odwołując się do type atrybutu obiektu KeyEvent.

Wartość zwracana przez lambdę onKeyEvent wskazuje, czy kluczowe zdarzenie jest obsługiwane. Jeśli Twoja aplikacja obsługuje kluczowe zdarzenie, zwróć wartość true, co spowoduje zatrzymanie propagacji zdarzenia.

Ten fragment kodu pokazuje, jak wywołać funkcję doSomething() gdy użytkownik zwolni klawisz S w komponencie Box:

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

Klawisze modyfikujące

Obiekt KeyEvent ma te atrybuty, które wskazują, czy klawisze modyfikujące są naciśnięte:

Opisuj dokładnie kluczowe zdarzenia obsługiwane przez Twoją aplikację. Ten fragment kodu wywołuje funkcję doSomething() tylko wtedy, gdy użytkownik zwolni tylko klawisz S. Jeśli użytkownik naciśnie dowolny klawisz modyfikujący, np. klawisz Shift, aplikacja nie wywoła tej funkcji.

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

Zdarzenia kliknięcia spacji i klawisza Enter

Klawisze Spacebar i Enter również wywołują zdarzenia kliknięcia. Użytkownicy mogą na przykład przełączać (odtwarzać lub wstrzymywać) odtwarzanie multimediów za pomocą klawisza Spacebar lub Enter obsługując zdarzenia kliknięcia w ten sposób:

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

Modyfikator clickable przechwytuje kluczowe zdarzenia i wywołuje wywołanie zwrotne onClick() , gdy zostanie naciśnięty klawisz Spacebar lub Enter. Dlatego w tym fragmencie kodu funkcja togglePausePlay() jest wywoływana przez naciśnięcie klawisza Spacebar lub Enter.

Nieobsługiwane kluczowe zdarzenia

Nieobsługiwane kluczowe zdarzenia są propagowane z komponentu, w którym wystąpiło zdarzenie, do otaczającego go komponentu zewnętrznego. W poniższym przykładzie komponent InnerComponent obsługuje kluczowe zdarzenia gdy zostanie zwolniony klawisz S, więc komponent OuterComponent nie otrzymuje żadnych kluczowych zdarzeń wywołanych przez zwolnienie klawisza S. Dlatego funkcja actionB() nigdy nie jest wywoływana.

Inne kluczowe zdarzenia w komponencie InnerComponent, np. zwolnienie klawisza D, mogą być obsługiwane przez komponent OuterComponent. Funkcja actionC() jest wywoływana, ponieważ kluczowe zdarzenie dotyczące zwolnienia klawisza D jest propagowane do komponentu OuterComponent.

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
            }
        }
    )
}

Modyfikator onKeyPreviewEvent

W niektórych przypadkach chcesz przechwycić kluczowe zdarzenie, zanim wywoła ono działanie domyślne. Typowym przykładem jest dodawanie niestandardowych skrótów do komponentu TextField. Ten fragment kodu umożliwia użytkownikom przejście do następnego komponentu, na którym można się skupić, przez naciśnięcie klawisza Tab.

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
        }
    }
)

Domyślnie komponent TextField dodaje znak tabulacji za każdym razem, gdy użytkownicy naciskają klawisz Tab, nawet jeśli kluczowe zdarzenie jest obsługiwane za pomocą modyfikatora onKeyEvent. Aby przenieść fokus klawiatury bez dodawania znaków tabulacji, obsłuż kluczowe zdarzenie przed wywołaniem działań powiązanych z tym zdarzeniem, tak jak w tym fragmencie kodu. Lambda onKeyPreviewEvent() przechwytuje kluczowe zdarzenie zwracając wartość true.

Komponent nadrzędny może przechwytywać kluczowe zdarzenie występujące w jego elementach podrzędnych. W tym fragmencie kodu, gdy użytkownicy nacisną klawisz S, wywoływana jest funkcja previewSKey() , a nie funkcja actionForPreview().

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

Lambda onPreviewKeyEvent() dla komponentu Box nie jest wywoływana gdy użytkownicy naciskają klawisz Tab. Lambda onPreviewKeyEvent() jest najpierw wywoływana w komponencie nadrzędnym, a potem onPreviewKeyEvent()w komponencie podrzędnym. Dzięki temu możesz implementować skróty klawiszowe obejmujące cały ekran.

Dodatkowe materiały

  • Pomocnik skrótów klawiszowych: ekran systemowy, który umożliwia użytkownikom wyszukiwanie skrótów klawiszowych oferowanych przez Twoją aplikację.