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 physique, 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 prêts à l'emploi.

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
Shift+Ctrl+Flèche haut/Flèche bas Sélectionner du texte jusqu'au début/à la fin du paragraphe BasicTextField, TextField
Shift+Alt+Flèche vers le haut/Flèche vers le bas ou Shift+Méta+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+Shift+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 avec le onKeyEvent modificateur. 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 touches. 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 de touches en vous référant à l'type attribut de l'objet KeyEvent.

La valeur renvoyée du lambda onKeyEvent indique si l'événement de touche est géré ou non. Renvoie 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 doSomething() fonction 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 les touches de modification sont enfoncées ou non :

Soyez précis dans la description des événements de touches gérés par votre application. L'extrait de code suivant appelle une doSomething() fonction uniquement si l'utilisateur relâche la touche S. Si l'utilisateur appuie sur une touche de modification, telle que la touche Shift, 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

Les touches Spacebar et Enter déclenchent également des événements de clic. Par exemple, les utilisateurs peuvent activer ou désactiver la lecture de contenus multimédias avec la touche Spacebar ou Enter en gérant les événements de clic comme suit :

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

Le modificateur clickable intercepte les événements de touches 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 de code.

Événements de touches non consommés

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

D'autres événements de touches sur InnerComponent, tels que le relâchement de la touche D, peuvent être gérés par le OuterComponent. La fonction actionC() est appelée, car l'événement de touche pour le relâchement de la touche D est propagé au 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 en est un exemple typique. L'extrait de code suivant permet aux utilisateurs de passer au composant suivant pouvant être sélectionné 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 Tab, même si l'événement de touche est géré avec le modificateur onKeyEvent. Pour déplacer le focus du 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 de code. Le onKeyPreviewEvent() lambda 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")
    }
}

Le lambda onPreviewKeyEvent() pour le composant Box n'est pas déclenché lorsque les utilisateurs appuient sur la touche Tab. 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