Gestire le azioni della tastiera

Quando l'utente attiva un componente di testo modificabile, ad esempio un TextField, e al dispositivo è collegata una tastiera fisica, tutti gli input vengono gestiti dal sistema. Puoi fornire scorciatoie da tastiera gestendo gli eventi chiave.

Scorciatoie da tastiera predefinite

Le seguenti scorciatoie da tastiera sono disponibili per impostazione predefinita.

Scorciatoia da tastiera Azione Componibili che supportano la scorciatoia
Maiusc+Ctrl+Freccia sinistra/Freccia destra Seleziona il testo fino all'inizio/alla fine della parola BasicTextField, TextField
Maiusc+Ctrl+Freccia su/Freccia giù Seleziona il testo fino all'inizio/alla fine del paragrafo BasicTextField, TextField
Maiusc+Alt+Freccia su/Freccia giù o Maiusc+Meta+Freccia sinistra/Freccia destra Seleziona il testo fino all'inizio/alla fine del testo BasicTextField, TextField
Maiusc+Freccia sinistra/Freccia destra Seleziona i personaggi BasicTextField, TextField
Ctrl+A Seleziona tutto BasicTextField, TextField
Ctrl+C/Ctrl+X/Ctrl+V Copia/taglia/incolla BasicTextField, TextField
Ctrl+Z/Ctrl+Maiusc+Z Annulla/Ripeti BasicTextField, TextField
PageDown/PageUp Scorri LazyColumn, il modificatore verticalScroll, il modificatore scrollable

Eventi chiave

In Compose, puoi gestire una singola pressione di un tasto con il modificatore onKeyEvent. Il modificatore accetta una funzione lambda che viene chiamata quando il componente modificato riceve un evento chiave. Un evento chiave viene descritto come un oggetto KeyEvent. Puoi ottenere le informazioni di ogni evento chiave facendo riferimento all'oggetto nella funzione lambda passata al modificatore onKeyEvent.

La pressione di un tasto invia due eventi chiave. Uno viene attivato quando l'utente preme il tasto, l'altro quando il tasto viene rilasciato. Puoi distinguere i due eventi chiave facendo riferimento all'attributo type dell'oggetto KeyEvent.

Il valore restituito della funzione lambda onKeyEvent indica se l'evento chiave viene gestito o meno. Restituisci true se la tua app gestisce l'evento chiave, il che interrompe la propagazione dell'evento.

Lo snippet seguente mostra come chiamare una funzione doSomething() quando l'utente rilascia il tasto S sul componente Box:

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

Tasti di modifica

Un oggetto KeyEvent ha i seguenti attributi che indicano se i tasti di modifica sono premuti o meno:

Descrivi in modo specifico gli eventi chiave gestiti dalla tua app. Lo snippet seguente chiama una funzione doSomething() solo se l'utente rilascia solo il tasto S. Se l'utente preme un tasto di modifica, ad esempio il tasto Maiusc, l'app non chiama la funzione.

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

Eventi di clic con la barra spaziatrice e il tasto Invio

Anche la barra spaziatrice e il tasto Invio attivano gli eventi di clic. Ad esempio, gli utenti possono attivare/disattivare (riprodurre o mettere in pausa) la riproduzione di contenuti multimediali con la barra spaziatrice o il tasto Invio gestendo gli eventi di clic nel seguente modo:

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

Il modificatore clickable intercetta gli eventi chiave e chiama il callback onClick() quando viene premuta la barra spaziatrice o il tasto Invio. Ecco perché la funzione togglePausePlay() viene chiamata premendo la barra spaziatrice o il tasto Invio nello snippet.

Eventi chiave non utilizzati

Gli eventi chiave non utilizzati vengono propagati dal componente in cui si è verificato l'evento al componente esterno che lo contiene. Nell'esempio seguente, InnerComponent consuma gli eventi chiave quando viene rilasciato il tasto S, quindi OuterComponent non riceve alcun evento chiave attivato dal rilascio del tasto S. Ecco perché la funzione actionB() non viene mai chiamata.

Altri eventi chiave su InnerComponent, come il rilascio del tasto D, possono essere gestiti da OuterComponent. La funzione actionC() viene chiamata perché l'evento chiave per il rilascio del tasto D viene propagato a 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
            }
        }
    )
}

Modificatore onKeyPreviewEvent

In alcuni casi d'uso, potresti voler intercettare un evento chiave prima che attivi l'azione predefinita. L'aggiunta di scorciatoie personalizzate a un TextField è un esempio tipico. Lo snippet seguente consente agli utenti di passare al componente attivabile successivo premendo il tasto 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
        }
    }
)

Per impostazione predefinita, il componente TextField aggiunge un carattere di tabulazione ogni volta che gli utenti premono il tasto Tab, anche se l'evento chiave viene gestito con il modificatore onKeyEvent. Per spostare la selezione della tastiera senza aggiungere caratteri di tabulazione, gestisci l'evento chiave prima di attivare le azioni associate all'evento chiave, come nello snippet. La funzione lambda onKeyPreviewEvent() intercetta l'evento chiave restituendo true.

Il componente principale può intercettare l'evento chiave che si verifica sui relativi componenti secondari. Nello snippet seguente, la funzione previewSKey() viene chiamata quando gli utenti premono il tasto S, anziché chiamare la funzione 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")
    }
}

Inoltre, la funzione lambda onPreviewKeyEvent() per il componente Box non viene attivata quando gli utenti premono il tasto Tab. La funzione lambda onPreviewKeyEvent() viene chiamata prima sul componente principale, poi viene chiamata onPreviewKeyEvent() nel componente secondario. Puoi implementare scorciatoie da tastiera a livello di schermo utilizzando questo comportamento.

Risorse aggiuntive