Gérer les actions du clavier

Lorsque l'utilisateur sélectionne un composant de texte modifiable, tel qu'un TextField, et que l'appareil est équipé d'un clavier matériel, toutes les entrées sont gérées par le système. Vous pouvez fournir des raccourcis clavier en gérant les événements de touches.

Raccourcis clavier par défaut

Les raccourcis clavier suivants sont disponibles par défaut.

Raccourci clavier Action Composables compatibles avec le raccourci
Maj+Ctrl+flèche vers la gauche/flèche vers la droite Sélectionner du texte jusqu'au début/à la fin du mot BasicTextField, TextField
Maj+Ctrl+Flèche vers le haut/Flèche vers le bas Sélectionner du texte jusqu'au début/à la fin du paragraphe BasicTextField, TextField
Maj+Alt+Flèche vers le haut/Flèche vers le bas ou Maj+Meta+Flèche vers la gauche/Flèche vers la droite Sélectionner du texte jusqu'au début/à la fin du texte BasicTextField, TextField
Maj+flèche vers la gauche/flèche vers la droite Sélectionner des caractères BasicTextField, TextField
Ctrl+A Tout sélectionner BasicTextField, TextField
Ctrl+C/Ctrl+X/Ctrl+V Copier/Couper/Coller BasicTextField, TextField
Ctrl+Z/Ctrl+Maj+Z Annuler/Rétablir BasicTextField, TextField
PageDown/PageUp Faire défiler LazyColumn, le modificateur verticalScroll, le modificateur scrollable

Événements clés

Dans Compose, vous pouvez gérer une frappe individuelle à l'aide du modificateur onKeyEvent. Le modificateur accepte un lambda appelé lorsque le composant modifié reçoit un événement de touche. Un événement de touche est décrit comme un objet KeyEvent. Vous pouvez obtenir les informations de chaque événement de touche en vous référant à l'objet dans le lambda transmis au modificateur onKeyEvent.

Une frappe envoie deux événements de touche. L'un est déclenché lorsque l'utilisateur appuie sur la touche, l'autre lorsqu'il la relâche. Vous pouvez distinguer les deux événements clés en vous référant à l'attribut type de l'objet KeyEvent.

La valeur de retour du lambda onKeyEvent indique si l'événement de touche est géré ou non. Renvoyez true si votre application gère l'événement de touche, ce qui arrête la propagation de l'événement.

L'extrait de code suivant montre comment appeler une fonction doSomething() lorsque l'utilisateur relâche la touche S sur le composant Box :

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

Touches de modification

Un objet KeyEvent possède les attributs suivants, qui indiquent si des touches de modification sont enfoncées ou non :

Décrivez précisément les événements clés gérés par votre application. L'extrait de code suivant appelle une fonction doSomething() uniquement si l'utilisateur relâche la touche S. Si l'utilisateur appuie sur une touche de modification, telle que la touche Maj, l'application n'appelle pas la fonction.

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

Événements de clic sur la barre d'espace et la touche Entrée

La barre d'espace et la touche Entrée déclenchent également des événements de clic. Par exemple, les utilisateurs peuvent activer ou désactiver (lire ou mettre en pause) la lecture de contenus multimédias à l'aide de la barre d'espace ou de la touche Entrée en gérant les événements de clic comme suit :

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

Le modificateur clickable intercepte les événements de touche et appelle le rappel onClick() lorsque l'utilisateur appuie sur la barre d'espace ou sur la touche Entrée. C'est pourquoi la fonction togglePausePlay() est appelée en appuyant sur la barre d'espace ou sur la touche Entrée dans l'extrait.

Événements clés non consommés

Les événements de touche non consommés sont propagés du composant où l'événement s'est produit vers le composant externe englobant. Dans l'exemple ci-dessous, InnerComponent consomme les événements de touche lorsque la touche S est relâchée. Par conséquent, OuterComponent ne reçoit aucun événement de touche déclenché par le relâchement de la touche S. C'est pourquoi la fonction actionB() n'est jamais appelée.

D'autres événements de touche sur InnerComponent, comme le relâchement de la touche D, peuvent être gérés par OuterComponent. La fonction actionC() est appelée, car l'événement de touche pour relâcher la touche D est propagé à 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
            }
        }
    )
}

Modificateur onKeyPreviewEvent

Dans certains cas d'utilisation, vous pouvez intercepter un événement de touche avant qu'il ne déclenche l'action par défaut. L'ajout de raccourcis personnalisés à un TextField est un cas d'utilisation courant. L'extrait de code suivant permet aux utilisateurs de passer au composant sélectionnable suivant en appuyant sur la touche 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
        }
    }
)

Par défaut, le composant TextField ajoute un caractère de tabulation chaque fois que les utilisateurs appuient sur la touche Tabulation, même si l'événement de touche est géré avec le modificateur onKeyEvent. Pour déplacer le focus clavier sans ajouter de caractères de tabulation, gérez l'événement de touche avant de déclencher les actions associées à l'événement de touche, comme dans l'extrait. Le lambda onKeyPreviewEvent() intercepte l'événement de touche en renvoyant true.

Le composant parent peut intercepter l'événement de touche qui se produit sur ses enfants. Dans l'extrait de code suivant, la fonction previewSKey() est appelée lorsque les utilisateurs appuient sur la touche S, au lieu d'appeler la fonction 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")
    }
}

La fonction lambda onPreviewKeyEvent() du composant Box n'est pas non plus déclenchée lorsque les utilisateurs appuient sur la touche Tabulation. Le lambda onPreviewKeyEvent() est d'abord appelé sur le composant parent, puis onPreviewKeyEvent() est appelé dans le composant enfant. Vous pouvez implémenter des raccourcis clavier à l'échelle de l'écran en utilisant ce comportement.

Ressources supplémentaires