Il est parfois nécessaire de remplacer le comportement de sélection par défaut des éléments à l'écran. Par exemple, vous pouvez regrouper des composables, empêcher sélectionner un composable donné, demander explicitement la sélection sur un composable, capturez ou relâchez le focus, ou redirigez le focus à l'entrée ou à la sortie. Ce explique comment modifier le comportement de sélection lorsque les valeurs par défaut ne correspondent pas à besoin.
Assurer une navigation cohérente au sein des groupes d'étude
Parfois, Jetpack Compose ne détermine pas immédiatement l'élément suivant
la navigation par onglets, surtout lorsque les Composables
parents complexes, comme les onglets et
les listes entrent en jeu.
Alors que la recherche ciblée suit généralement l'ordre de déclaration de Composables
,
cela est impossible dans certains cas, par exemple lorsque l'un des Composables
dans le
est un défilement horizontal qui n'est pas entièrement visible. Ceci est illustré dans
l'exemple ci-dessous.
Jetpack Compose peut décider de sélectionner l'élément suivant le plus proche du début de à l'écran, comme indiqué ci-dessous, plutôt que de poursuivre sur le chemin attendu pour navigation unidirectionnelle:
Dans cet exemple, il est clair que les développeurs n'avaient pas l'intention de se concentrer passez de l'onglet Chocolats à la première image ci-dessous, puis revenez à la Onglet Pâtisseries. Au lieu de cela, il voulait se concentrer sur les onglets jusqu'à ce que le dernier onglet, puis concentrez-vous sur le contenu interne:
Dans les cas où il est important qu'un groupe de composables gagne la priorité
séquentiellement, comme dans la ligne de tabulation de l'exemple précédent, vous devez encapsuler
le Composable
dans un parent ayant le modificateur focusGroup()
:
LazyVerticalGrid(columns = GridCells.Fixed(4)) { item(span = { GridItemSpan(maxLineSpan) }) { Row(modifier = Modifier.focusGroup()) { FilterChipA() FilterChipB() FilterChipC() } } items(chocolates) { SweetsCard(sweets = it) } }
La navigation bidirectionnelle recherche le composable le plus proche pour l'élément donné
direction (si un élément d'un autre groupe est plus proche d'un élément non entièrement visible)
dans le groupe actuel, la navigation choisit l'élément le plus proche. Pour éviter cela,
vous pouvez appliquer le modificateur focusGroup()
.
FocusGroup
fait apparaître un groupe entier comme une seule entité en termes d'attention.
mais le groupe lui-même ne reçoit pas l'attention. Au lieu de cela, l'enfant le plus proche
se concentrer à la place. Ainsi, la navigation sait qu'il faut accéder
élément avant de quitter le groupe.
Dans ce cas, les trois instances de FilterChip
seront sélectionnées avant la
SweetsCard
éléments, même si les SweetsCards
sont entièrement visibles par le
utilisateur et certains FilterChip
sont peut-être masqués. Cela se produit parce que le
Le modificateur focusGroup
indique au gestionnaire de sélection d'ajuster l'ordre dans lequel les éléments
afin que la navigation soit plus facile et plus cohérente avec l'interface utilisateur.
Sans le modificateur focusGroup
, si FilterChipC
n'était pas visible, sélectionner
la navigation
la retiendrait en dernier. Cependant, l'ajout d'un tel modificateur
seulement visible, mais elle sera également mise en avant juste après FilterChipB
, comme
s'attendent à ce que les utilisateurs.
Rendre un composable sélectionnable
Certains composables sont sélectionnables à la conception, comme un bouton ou un composable avec
le modificateur clickable
qui lui est associé. Si vous souhaitez ajouter spécifiquement
comportement sélectionnable à un composable, utilisez le modificateur focusable
:
var color by remember { mutableStateOf(Green) } Box( Modifier .background(color) .onFocusChanged { color = if (it.isFocused) Blue else Green } .focusable() ) { Text("Focusable 1") }
Rendre un composable non sélectionnable
Il peut y avoir des situations dans lesquelles certains de vos éléments ne devraient pas participer
au premier plan. Dans ces rares cas, vous pouvez profiter du canFocus property
pour empêcher le ciblage d'un Composable
.
var checked by remember { mutableStateOf(false) } Switch( checked = checked, onCheckedChange = { checked = it }, // Prevent component from being focused modifier = Modifier .focusProperties { canFocus = false } )
Demander le focus au clavier avec FocusRequester
Dans certains cas, vous pouvez demander explicitement la concentration en réponse à une l'interaction de l'utilisateur. Par exemple, vous pouvez demander à un utilisateur s'il souhaite redémarrer qui remplissent un formulaire, et s'ils appuient sur « oui » vous devez recentrer le premier champ sous cette forme.
La première chose à faire est d'associer un objet FocusRequester
au
composable sur lequel vous souhaitez sélectionner le clavier. Dans le code suivant,
extrait, un objet FocusRequester
est associé à un TextField
en définissant un
modificateur appelé Modifier.focusRequester
:
val focusRequester = remember { FocusRequester() } var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { text = it }, modifier = Modifier.focusRequester(focusRequester) )
Vous pouvez appeler la méthode requestFocus
de FocusRequester pour envoyer des requêtes de sélection réelles. Vous devez appeler cette méthode en dehors d'un contexte Composable
.
(sinon, elle est réexécutée à chaque recomposition). L'extrait suivant
montre comment demander au système de déplacer le curseur du clavier lorsque le bouton est
cliqué:
val focusRequester = remember { FocusRequester() } var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { text = it }, modifier = Modifier.focusRequester(focusRequester) ) Button(onClick = { focusRequester.requestFocus() }) { Text("Request focus on TextField") }
Capturer et relâcher la mise au point
Vous pouvez exploiter la concentration pour guider vos utilisateurs afin qu'ils fournissent les données appropriées pour votre application. doit mener à bien sa tâche, par exemple, obtenir une adresse e-mail ou un numéro de téléphone valides numéro. Les états d'erreur informent vos utilisateurs de ce qui se passe, peut avoir besoin d'un champ contenant des informations erronées pour rester concentré jusqu'à ce qu'il soit ou corriger un problème.
Pour capturer le focus, vous pouvez appeler la méthode captureFocus()
, puis
libérez-le ensuite avec la méthode freeFocus()
à la place, comme dans l'exemple
Exemple:
val textField = FocusRequester() TextField( value = text, onValueChange = { text = it if (it.length > 3) { textField.captureFocus() } else { textField.freeFocus() } }, modifier = Modifier.focusRequester(textField) )
Priorité des modificateurs de mise au point
Modifiers
peuvent être considérés comme des éléments qui n'ont qu'un seul enfant. Ainsi, lorsque vous mettez en file d'attente
chaque Modifier
à gauche (ou en haut) encapsule la Modifier
qui suit
vers la droite (ou en dessous). Cela signifie que le second Modifier
est contenu à l'intérieur
le premier. Ainsi, lorsque vous déclarez deux focusProperties
, seul le premier
car celles-ci sont contenues dans la première.
Pour clarifier le concept, consultez le code suivant:
Modifier .focusProperties { right = item1 } .focusProperties { right = item2 } .focusable()
Dans ce cas, le focusProperties
indiquant item2
comme le focus droit sera
ne doit pas être utilisé, car il est contenu dans l'énoncé précédent ; item1
sera donc
utilisée.
Grâce à cette approche, un parent peut également rétablir le comportement par défaut
à l'aide de FocusRequester.Default
:
Modifier .focusProperties { right = Default } .focusProperties { right = item1 } .focusProperties { right = item2 } .focusable()
Le parent ne doit pas nécessairement faire partie de la même chaîne de modificateur. Un parent
Un composable peut écraser la propriété de focus d'un composable enfant. Par exemple :
Prenons l'exemple FancyButton
qui rend le bouton non sélectionnable:
@Composable fun FancyButton(modifier: Modifier = Modifier) { Row(modifier.focusProperties { canFocus = false }) { Text("Click me") Button(onClick = { }) { Text("OK") } } }
Pour activer à nouveau ce bouton, définissez canFocus
sur true
:
FancyButton(Modifier.focusProperties { canFocus = true })
Comme chaque Modifier
, les actions axées sur un élément se comportent différemment selon l'ordre.
lorsque vous les déclarez. Par exemple, un code comme celui-ci rend Box
sélectionnable, mais FocusRequester
n'est pas associé à celui-ci, car il
est déclarée après l'élément sélectionnable.
Box( Modifier .focusable() .focusRequester(Default) .onFocusChanged {} )
N'oubliez pas qu'un focusRequester
est associé au premier
sélectionnable en dessous de lui dans la hiérarchie, donc ce focusRequester
pointe vers
premier enfant sélectionnable. Si aucun n'est disponible, il ne pointera vers rien.
Toutefois, comme Box
est sélectionnable (grâce au modificateur focusable()
),
vous pouvez y accéder en utilisant
la navigation bidirectionnelle.
Autre exemple : l'une ou l'autre des méthodes suivantes fonctionne, car onFocusChanged()
qui fait référence au premier élément sélectionnable qui apparaît après
les modificateurs focusable()
ou focusTarget()
.
Box( Modifier .onFocusChanged {} .focusRequester(Default) .focusable() ) |
Box( Modifier .focusRequester(Default) .onFocusChanged {} .focusable() ) |
Rediriger le curseur à l'entrée ou à la sortie
Parfois, vous devez fournir un type de navigation très spécifique, comme celui comme illustré dans l'animation ci-dessous:
Avant d'entrer dans les détails, il est important de comprendre
le comportement de la recherche ciblée. Sans aucune modification, une fois que la recherche de focus
atteint l'élément Clickable 3
en appuyant sur DOWN
sur le pavé directionnel (ou l'équivalent
flèche) permet de déplacer le curseur vers l'élément affiché sous Column
,
en quittant le groupe et
en ignorant celui de droite. S'il n'y a pas de
éléments sélectionnables disponibles, le curseur ne bouge pas, mais reste activé
Clickable 3
Pour modifier ce comportement et fournir la navigation prévue, vous pouvez utiliser le
Le modificateur focusProperties
, qui vous aide à gérer ce qui se passe lorsque la sélection
la recherche entre ou quitte le Composable
:
val otherComposable = remember { FocusRequester() } Modifier.focusProperties { exit = { focusDirection -> when (focusDirection) { Right -> Cancel Down -> otherComposable else -> Default } } }
Il est possible de diriger le curseur vers un élément Composable
spécifique chaque fois qu'il entre
ou sort d'une certaine partie de la hiérarchie, par exemple, lorsque votre UI comporte deux
et vous voulez vous assurer
qu'à chaque fois que la première est traitée,
le focus passe à la seconde:
Dans ce GIF, une fois que le curseur a atteint le Clickable 3 Composable
dans Column
1,
l'élément suivant en cours de sélection est Clickable 4
dans un autre Column
. Ce comportement
Vous pouvez obtenir ce résultat en combinant focusDirection
avec enter
et exit
.
dans le modificateur focusProperties
. Ils ont tous les deux besoin
d'un lambda qui prend
comme paramètre la direction d'où provient le focus et renvoie une
FocusRequester
Ce lambda peut se comporter
de trois manières différentes: renvoyer
FocusRequester.Cancel
empêche la mise au point de continuer, tandis que
FocusRequester.Default
ne modifie pas son comportement. En fournissant
FocusRequester
attaché à un autre Composable
fait passer le curseur sur celle-ci
des Composable
spécifiques.
Modifier la direction d'avance de la mise au point
Pour passer à l'élément suivant ou dans une direction précise, vous pouvez
utilisez le modificateur onPreviewKey
et impliquez LocalFocusManager
pour
déplacez le curseur avec le modificateur moveFocus
.
L'exemple suivant illustre le comportement par défaut du mécanisme de focus: lorsqu'un
Une pression de touche tab
est détectée, le curseur passe à l'élément suivant.
liste. Bien que cela ne soit pas quelque chose
que vous devez généralement configurer, il est important
de connaître le fonctionnement interne du système afin de pouvoir modifier
comportemental.
val focusManager = LocalFocusManager.current var text by remember { mutableStateOf("") } TextField( value = text, onValueChange = { text = it }, modifier = Modifier.onPreviewKeyEvent { when { KeyEventType.KeyUp == it.type && Key.Tab == it.key -> { focusManager.moveFocus(FocusDirection.Next) true } else -> false } } )
Dans cet exemple, la fonction focusManager.moveFocus()
déplace le curseur vers
l'élément spécifié, ou dans la direction implicite dans le paramètre de fonction.
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Réagir à la concentration
- Curseur dans Compose
- Modifier l'ordre de passage du curseur