Obsługa działań na klawiaturze

Gdy użytkownik aktywuje element tekstowy, który można edytować, np. TextField, a do urządzenia jest podłączona klawiatura sprzętowa, system przejmuje wszystkie dane wejściowe. Skróty klawiszowe możesz udostępniać, obsługując kluczowe zdarzenia.

Domyślne skróty klawiszowe

Poniższe skróty klawiszowe są dostępne od razu.

Skrót klawiszowy Działanie Komponenty obsługujące skrót
Shift + Ctrl + strzałka w lewo lub w prawo Zaznacz tekst do początku/końca wyrazu 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 / w prawo Wybieranie znaków BasicTextField, TextField
Ctrl + A Zaznacz wszystkie BasicTextField, TextField
Ctrl + C lub Ctrl + X lub 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

Najważniejsze wydarzenia

W sekcji Redagowanie możesz obsługiwać poszczególne naciśnięcia klawiszy za pomocą modyfikatora onKeyEvent. Modyfikator przyjmuje funkcję lambda, która jest wywoływana, gdy zmodyfikowany komponent otrzyma kluczowe zdarzenie. Kluczowe zdarzenie jest opisane jako obiekt KeyEvent. Informacje o każdym kluczowym zdarzeniu możesz uzyskać, odwołując się do obiektu w funkcji lambda przekazywana do modyfikatora onKeyEvent.

Naciśnięcie klawisza powoduje wysłanie 2 kluczowych zdarzeń. Jeden jest uruchamiany, gdy użytkownik naciśnie klawisz, a drugi, gdy go puści. Te 2 kluczowe zdarzenia możesz odróżnić, korzystając z atrybutu type obiektu KeyEvent.

Wartość zwracana przez funkcję onKeyEventlambda wskazuje, czy kluczowe zdarzenie zostało przetworzone. Zwraca wartość true, jeśli Twoja aplikacja obsługuje kluczowe zdarzenie, co powoduje zatrzymanie propagacji tego zdarzenia.

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

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

Klawisze modyfikujące

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

Szczegółowo opisz kluczowe zdarzenia obsługiwane przez aplikację. Ten fragment kodu wywołuje funkcję doSomething() tylko wtedy, gdy użytkownik zwolni tylko klucz S. Jeśli użytkownik naciśnie dowolny klawisz modyfikujący, np. klawisz Shift, aplikacja nie wywołuje 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")
}

Spacja i Wpisz kluczowe zdarzenia kliknięcia

a także zdarzenia kliknięcia spacja i Enter. Użytkownicy mogą na przykład włączać i wyłączać (odtwarzać lub wstrzymywać) odtwarzanie multimediów za pomocą klawisza spacja lub Enter, obsługując zdarzenia kliknięcia w ten sposób:

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

Modyfikator clickable przechwytuje zdarzenia klawiszy i wywołuje wywołanie zwrotne onClick(), gdy naciśniesz klawisz spacja lub Enter. Dlatego funkcja togglePausePlay() jest nazywana naciskając spację lub Enter we fragmencie kodu.

Niewykorzystane kluczowe zdarzenia

Nieużywane kluczowe zdarzenia są przekazywane z komponentu gdzie zdarzenie wystąpiło na nadrzędnym komponencie. W poniższym przykładzie reguła InnerComponent wykorzystuje kluczowe zdarzenia po zwolnieniu klucza S, więc OuterComponent nie odbiera żadnych uruchomionych kluczowych zdarzeń przez zwolnienie klucza S. Dlatego funkcja actionB() nigdy nie jest wywoływana.

Inne kluczowe zdarzenia w usłudze InnerComponent, takie jak zwolnienie klucza D, może być obsługiwany przez OuterComponent. Funkcja actionC() jest wywoływana, ponieważ kluczowe zdarzenie dla funkcji zwolnienie klucza D zostanie rozpowszechnione w 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 może Ci się przydać przechwytywanie kluczowych zdarzeń przed wywołaniem działania domyślnego. Dodawanie niestandardowych skrótów do TextField to typowa sytuacja. Ten fragment kodu umożliwia użytkownikom przejście do następnego komponentu, który można zaznaczyć, przez naciskając klawisz 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żytkownik naciśnie klawisz Tab, nawet jeśli zdarzenie związane z klawiszem jest obsługiwane przez modyfikator onKeyEvent. Aby przenieść zaznaczenie bez dodawania znaków tabulacji: obsługuje kluczowe zdarzenie przed uruchomieniem działań powiązanych z kluczowym zdarzeniem, np. we fragmencie kodu. Funkcja lambda onKeyPreviewEvent() przechwytuje kluczowe zdarzenie powrót true.

Komponent nadrzędny może przechwytywać kluczowe zdarzenie mające miejsce w jego elementach podrzędnych. W tym fragmencie kodu funkcja previewSKey() jest wywoływana, gdy użytkownik naciśnie klawisz S, zamiast wywołać funkcję 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 też uruchamiana, gdy użytkownicy naciskają klawisz Tab. Najpierw funkcja lambda onPreviewKeyEvent() jest wywoływana przez komponent nadrzędny, a następnie wywoływana jest funkcja onPreviewKeyEvent() w komponencie podrzędnym. W ten sposób możesz zaimplementować skróty klawiszowe obejmujące cały ekran.

Dodatkowe materiały