Share via


Navigation au focus pour le clavier, le boîtier de commande, le contrôle à distance et les outils d’accessibilité

Clavier, remote et D-pad

Utilisez la navigation focus pour fournir des expériences d’interaction complètes et cohérentes dans vos applications Windows et des contrôles personnalisés pour les utilisateurs du clavier, les personnes handicapées et d’autres exigences d’accessibilité, ainsi que l’expérience de 10 pieds des écrans de télévision et de la Xbox One.

Vue d’ensemble

La navigation focus fait référence au mécanisme sous-jacent qui permet aux utilisateurs de naviguer et d’interagir avec l’interface utilisateur d’une application Windows à l’aide d’un clavier, d’un boîtier de commande ou d’une télécommande.

Notes

Les appareils d’entrée sont généralement classés en tant qu’appareils de pointage, tels que le pavé tactile, le pavé tactile, le stylet et la souris, et les appareils non pointants, tels que le clavier, le boîtier de commande et la télécommande.

Cette rubrique explique comment optimiser une application Windows et créer des expériences d’interaction personnalisées pour les utilisateurs qui s’appuient sur des types d’entrée non pointants.

Bien que nous nous concentrions sur l’entrée au clavier pour les contrôles personnalisés dans les applications Windows sur PC, une expérience de clavier bien conçue est également importante pour les claviers logiciels tels que le clavier tactile et le clavier à l’écran (OSK), prenant en charge les outils d’accessibilité tels que le Narrateur Windows et prenant en charge l’expérience 10 pieds.

Consultez Gérer l’entrée de pointeur pour obtenir des conseils sur la création d’expériences personnalisées dans des applications Windows pour pointer des appareils.

Pour plus d’informations générales sur la création d’applications et d’expériences pour le clavier, consultez Interaction clavier.

Règle générale

Seuls les éléments d’interface utilisateur qui nécessitent une interaction utilisateur doivent prendre en charge la navigation au focus, les éléments qui ne nécessitent pas d’action, comme les images statiques, n’ont pas besoin du focus clavier. Les lecteurs d’écran et les outils d’accessibilité similaires annoncent toujours ces éléments statiques, même s’ils ne sont pas inclus dans la navigation focus.

Il est important de se rappeler que contrairement à la navigation à l’aide d’un dispositif de pointeur tel qu’une souris ou une touche tactile, la navigation au focus est linéaire. Lorsque vous implémentez la navigation focus, réfléchissez à la façon dont un utilisateur interagira avec votre application et à ce que doit être la navigation logique. Dans la plupart des cas, nous vous recommandons de suivre le modèle de lecture préféré de la culture de l’utilisateur.

Voici d’autres considérations à prendre en compte pour la navigation :

  • Les contrôles sont-ils regroupés logiquement ?
  • Existe-t-il des groupes de contrôles plus importants ?
    • Si oui, ces groupes contiennent-ils des sous-groupes ?
  • La disposition nécessite-t-elle une navigation directionnelle personnalisée (touches de direction) et un ordre de tabulation personnalisé ?

Le livre électronique Engineering Software for Accessibility contient un excellent chapitre sur la conception de la hiérarchie logique.

Navigation directionnelle 2D pour le clavier

La région de navigation interne 2D d’un contrôle, ou d’un groupe de contrôles, est appelée « zone directionnelle ». Lorsque le focus se déplace sur cet objet, les touches de direction du clavier (gauche, droite, haut et bas) peuvent être utilisées pour naviguer entre les éléments enfants dans la zone directionnelle.

zone directionnelle2D Zone de navigation interne, ou zone directionnelle, d’un groupe de contrôles

Vous pouvez utiliser la propriété XYFocusKeyboardNavigation (qui a des valeurs possibles Auto, Enabled ou Disabled) pour gérer la navigation interne 2D avec les touches de direction du clavier.

Notes

L’ordre de tabulation n’est pas affecté par cette propriété. Pour éviter une expérience de navigation confuse, nous vous recommandons de ne pas spécifier explicitement les éléments enfants d’une zone directionnelle dans l’ordre de navigation tabulation de votre application. Pour plus d’informations sur le comportement de tabulation d’un élément, consultez les propriétés UIElement.TabFocusNavigation et TabIndex .

Auto (comportement par défaut)

Lorsqu’il est défini sur Auto, le comportement de navigation directionnelle est déterminé par l’ancêtre ou la hiérarchie d’héritage de l’élément. Si tous les ancêtres sont en mode par défaut (défini sur Auto), la navigation directionnelle avec le clavier n’est pas prise en charge.

Désactivé

Définissez XYFocusKeyboardNavigation sur Désactivé pour bloquer la navigation directionnelle vers le contrôle et ses éléments enfants.

Comportement XYFocusKeyboardNavigation désactivéXYFocusKeyboardNavigation désactivé

Dans cet exemple, le StackPanel principal (ContainerPrimary) a XYFocusKeyboardNavigation défini sur Activé. Tous les éléments enfants héritent de ce paramètre et peuvent être parcourus avec les touches de direction. Toutefois, les éléments B3 et B4 se trouvent dans un StackPanel secondaire (ContainerSecondary) avec XYFocusKeyboardNavigation défini sur Désactivé, ce qui remplace le conteneur principal et désactive la navigation par touche de direction vers lui-même et entre ses éléments enfants.

<Grid 
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" 
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="75"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
                Grid.Row="0" 
                FontWeight="ExtraBold" 
                HorizontalTextAlignment="Center"
                TextWrapping="Wrap" 
                Padding="10" />
    <StackPanel Name="ContainerPrimary" 
                XYFocusKeyboardNavigation="Enabled" 
                KeyDown="ContainerPrimary_KeyDown" 
                Orientation="Horizontal" 
                BorderBrush="Green" 
                BorderThickness="2" 
                Grid.Row="1" 
                Padding="10" 
                MaxWidth="200">
        <Button Name="B1" 
                Content="B1" 
                GettingFocus="Btn_GettingFocus" />
        <Button Name="B2" 
                Content="B2" 
                GettingFocus="Btn_GettingFocus" />
        <StackPanel Name="ContainerSecondary" 
                    XYFocusKeyboardNavigation="Disabled" 
                    Orientation="Horizontal" 
                    BorderBrush="Red" 
                    BorderThickness="2">
            <Button Name="B3" 
                    Content="B3" 
                    GettingFocus="Btn_GettingFocus" />
            <Button Name="B4" 
                    Content="B4" 
                    GettingFocus="Btn_GettingFocus" />
        </StackPanel>
    </StackPanel>
</Grid>

Activé

Définissez XYFocusKeyboardNavigation sur Activé pour prendre en charge la navigation directionnelle 2D vers un contrôle et chacun de ses objets enfants UIElement .

Lorsqu’elle est définie, la navigation avec les touches de direction est limitée aux éléments de la zone directionnelle. La navigation par tabulation n’est pas affectée, car tous les contrôles restent accessibles via leur hiérarchie d’ordre de tabulation.

Comportement XYFocusKeyboardNavigation activéXYFocusKeyboardNavigation activé

Dans cet exemple, le StackPanel principal (ContainerPrimary) a XYFocusKeyboardNavigation défini sur Activé. Tous les éléments enfants héritent de ce paramètre et peuvent être parcourus avec les touches de direction. Les éléments B3 et B4 se trouvent dans un StackPanel secondaire (ContainerSecondary) où XYFocusKeyboardNavigation n’est pas défini, qui hérite ensuite du paramètre de conteneur principal. L’élément B5 ne se trouve pas dans une zone directionnelle déclarée et ne prend pas en charge la navigation par touche de direction, mais prend en charge le comportement de navigation par onglet standard.

<Grid
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="100"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
               Grid.Row="0"
               FontWeight="ExtraBold"
               HorizontalTextAlignment="Center"
               TextWrapping="Wrap"
               Padding="10" />
    <StackPanel Grid.Row="1"
                Orientation="Horizontal"
                HorizontalAlignment="Center">
        <StackPanel Name="ContainerPrimary"
                    XYFocusKeyboardNavigation="Enabled"
                    KeyDown="ContainerPrimary_KeyDown"
                    Orientation="Horizontal"
                    BorderBrush="Green"
                    BorderThickness="2"
                    Padding="5" Margin="5">
            <Button Name="B1"
                    Content="B1"
                    GettingFocus="Btn_GettingFocus" Margin="5" />
            <Button Name="B2"
                    Content="B2"
                    GettingFocus="Btn_GettingFocus" />
            <StackPanel Name="ContainerSecondary"
                        Orientation="Horizontal"
                        BorderBrush="Red"
                        BorderThickness="2"
                        Margin="5">
                <Button Name="B3"
                        Content="B3"
                        GettingFocus="Btn_GettingFocus"
                        Margin="5" />
                <Button Name="B4"
                        Content="B4"
                        GettingFocus="Btn_GettingFocus"
                        Margin="5" />
            </StackPanel>
        </StackPanel>
        <Button Name="B5"
                Content="B5"
                GettingFocus="Btn_GettingFocus"
                Margin="5" />
    </StackPanel>
</Grid>

Vous pouvez avoir plusieurs niveaux de zones directionnelles imbriquées. Si tous les éléments parents ont XYFocusKeyboardNavigation défini sur Activé, les limites de la région de navigation interne sont ignorées.

Voici un exemple de deux zones directionnelles imbriquées au sein d’un élément qui ne prend pas explicitement en charge la navigation directionnelle 2D. Dans ce cas, la navigation directionnelle n’est pas prise en charge entre les deux zones imbriquées.

Comportement XYFocusKeyboardNavigation activé et imbriquéXYFocusKeyboardNavigation activé et imbriqué

Voici un exemple plus complexe de trois zones directionnelles imbriquées où :

  • Lorsque B1 a le focus, seul B5 peut être redirigé vers (et inversement), car il existe une limite de zone directionnelle où XYFocusKeyboardNavigation est défini sur Désactivé, ce qui rend B2, B3 et B4 inaccessible avec les touches de direction
  • Lorsque B2 a le focus, seul B3 peut être redirigé vers (et inversement), car la limite de zone directionnelle empêche la navigation en touche de direction vers B1, B4 et B5
  • Lorsque B4 a le focus, la touche Tab doit être utilisée pour naviguer entre les contrôles

XYFocusKeyboardNavigation activé et comportement imbriqué complexe

XYFocusKeyboardNavigation activé et comportement imbriqué complexe

Navigation par onglet

Bien que les touches de direction puissent être utilisées pour la navigation directionnelle 2D avec un contrôle ou un groupe de contrôles, la touche Tab peut être utilisée pour naviguer entre tous les contrôles d’une application Windows.

Tous les contrôles interactifs prennent en charge la navigation par touche Tab par défaut (IsEnabled et la propriété IsTabStop ont la valeur true), avec l’ordre de tabulation logique dérivé de la disposition de contrôle dans votre application. Toutefois, l’ordre par défaut ne correspond pas nécessairement à l’ordre visuel. La position d’affichage réelle peut dépendre du conteneur de disposition parent et de certaines propriétés que vous pouvez définir sur les éléments enfants pour influencer la disposition.

Évitez un ordre de tabulation personnalisé qui fait que le focus saute dans votre application. Par exemple, une liste de contrôles dans un formulaire doit avoir un ordre de tabulation qui circule de haut en bas et de gauche à droite (en fonction des paramètres régionaux).

Dans cette section, nous décrivons comment cet ordre de tabulation peut être entièrement personnalisé en fonction de votre application.

Définir le comportement de navigation de l’onglet

La propriété TabFocusNavigationd’UIElement spécifie le comportement de navigation par onglet pour l’ensemble de son arborescence d’objets (ou sa zone directionnelle).

Notes

Utilisez cette propriété au lieu de la propriété Control.TabNavigation pour les objets qui n’utilisent pas de ControlTemplate pour définir leur apparence.

Comme nous l’avons mentionné dans la section précédente, pour éviter une expérience de navigation confuse, nous vous recommandons de ne pas spécifier explicitement les éléments enfants d’une zone directionnelle dans l’ordre de navigation tabulation de votre application. Pour plus d’informations sur le comportement de tabulation d’un élément, consultez UIElement.TabFocusNavigation et les propriétés TabIndex .

Pour les versions antérieures à Windows 10 Creators Update (build 10.0.15063), les paramètres d’onglet étaient limités aux objets ControlTemplate. Pour plus d’informations, consultez Control.TabNavigation.

TabFocusNavigation a une valeur de type KeyboardNavigationMode avec les valeurs possibles suivantes (notez que ces exemples ne sont pas des groupes de contrôles personnalisés et ne nécessitent pas de navigation interne avec les touches de direction) :

  • Les index Tab locaux (par défaut) sont reconnus sur la sous-arborescence locale à l’intérieur du conteneur. Pour cet exemple, l’ordre de tabulation est B1, B2, B3, B4, B5, B6, B7, B1.

    Comportement de navigation de l’onglet « Local »

    Comportement de navigation de l’onglet « Local »

  • Une fois Le conteneur et tous les éléments enfants reçoivent le focus une fois. Pour cet exemple, l’ordre de tabulation est B1, B2, B7, B1 (la navigation interne avec la touche de direction est également illustrée).

    Comportement de navigation de l’onglet « Une fois »

    Comportement de navigation de l’onglet « Une fois »

  • Cycle
    Le focus revient à l’élément focusable initial à l’intérieur d’un conteneur. Pour cet exemple, l’ordre de tabulation est B1, B2, B3, B4, B5, B6, B2...

    Comportement de navigation de l’onglet « Cycle »

    Comportement de navigation de l’onglet « Cycle »

Voici le code des exemples précédents (avec TabFocusNavigation ="Cycle »).

<Grid 
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" 
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="300"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
               Grid.Row="0" 
               FontWeight="ExtraBold" 
               HorizontalTextAlignment="Center"
               TextWrapping="Wrap" 
               Padding="10" />
    <StackPanel Name="ContainerPrimary"
                KeyDown="Container_KeyDown" 
                Orientation="Horizontal" 
                HorizontalAlignment="Center"
                BorderBrush="Green" 
                BorderThickness="2" 
                Grid.Row="1" 
                Padding="10" 
                MaxWidth="200">
        <Button Name="B1" 
                Content="B1" 
                GettingFocus="Btn_GettingFocus" 
                Margin="5"/>
        <StackPanel Name="ContainerSecondary" 
                    KeyDown="Container_KeyDown"
                    XYFocusKeyboardNavigation="Enabled" 
                    TabFocusNavigation ="Cycle"
                    Orientation="Vertical" 
                    VerticalAlignment="Center"
                    BorderBrush="Red" 
                    BorderThickness="2"
                    Padding="5" Margin="5">
            <Button Name="B2" 
                    Content="B2" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B3" 
                    Content="B3" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B4" 
                    Content="B4" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B5" 
                    Content="B5" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
            <Button Name="B6" 
                    Content="B6" 
                    GettingFocus="Btn_GettingFocus" 
                    Margin="5"/>
        </StackPanel>
        <Button Name="B7" 
                Content="B7" 
                GettingFocus="Btn_GettingFocus" 
                Margin="5"/>
    </StackPanel>
</Grid>

TabIndex

Utilisez TabIndex pour spécifier l’ordre dans lequel les éléments reçoivent le focus lorsque l’utilisateur navigue dans les contrôles à l’aide de la touche Tab. Un contrôle avec un index tabulation inférieur reçoit le focus avant un contrôle avec un index supérieur.

Lorsqu’aucun contrôle TabIndex n’est spécifié, une valeur d’index supérieure à la valeur d’index la plus élevée (et la priorité la plus basse) de tous les contrôles interactifs de l’arborescence visuelle lui est attribuée, en fonction de l’étendue.

Tous les éléments enfants d’un contrôle sont considérés comme une étendue et, si l’un de ces éléments a également des éléments enfants, ils sont considérés comme une autre étendue. Toute ambiguïté est résolue en choisissant le premier élément de l’arborescence visuelle de l’étendue.

Pour exclure un contrôle de l’ordre de tabulation, définissez la propriété IsTabStop surfalse.

Remplacez l’ordre de tabulation par défaut en définissant la propriété TabIndex .

Notes

TabIndex fonctionne de la même façon avec UIElement.TabFocusNavigation et Control.TabNavigation.

Ici, nous montrons comment la navigation au focus peut être affectée par la propriété TabIndex sur des éléments spécifiques.

Navigation de l’onglet « Local » avec le comportement TabIndex

Navigation de l’onglet « Local » avec le comportement TabIndex

Dans l’exemple précédent, il existe deux étendues :

  • B1, zone directionnelle (B2 - B6) et B7
  • zone directionnelle (B2 - B6)

Lorsque B3 (dans la zone directionnelle) obtient le focus, l’étendue change et la navigation par onglet est transférée vers la zone directionnelle où le meilleur candidat pour le focus suivant est identifié. Dans ce cas, B2 suivi de B4, B5 et B6. L’étendue change ensuite à nouveau et le focus passe à B1.

Voici le code de cet exemple.

<Grid
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    TabFocusNavigation="Cycle">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="300"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <TextBlock Name="KeyPressed"
               Grid.Row="0"
               FontWeight="ExtraBold"
               HorizontalTextAlignment="Center"
               TextWrapping="Wrap"
               Padding="10" />
    <StackPanel Name="ContainerPrimary"
                KeyDown="Container_KeyDown"
                Orientation="Horizontal"
                HorizontalAlignment="Center"
                BorderBrush="Green"
                BorderThickness="2"
                Grid.Row="1"
                Padding="10"
                MaxWidth="200">
        <Button Name="B1"
                Content="B1"
                TabIndex="1"
                ToolTipService.ToolTip="TabIndex = 1"
                GettingFocus="Btn_GettingFocus"
                Margin="5"/>
        <StackPanel Name="ContainerSecondary"
                    KeyDown="Container_KeyDown"
                    TabFocusNavigation ="Local"
                    Orientation="Vertical"
                    VerticalAlignment="Center"
                    BorderBrush="Red"
                    BorderThickness="2"
                    Padding="5" Margin="5">
            <Button Name="B2"
                    Content="B2"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B3"
                    Content="B3"
                    TabIndex="3"
                    ToolTipService.ToolTip="TabIndex = 3"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B4"
                    Content="B4"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B5"
                    Content="B5"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
            <Button Name="B6"
                    Content="B6"
                    GettingFocus="Btn_GettingFocus"
                    Margin="5"/>
        </StackPanel>
        <Button Name="B7"
                Content="B7"
                TabIndex="2"
                ToolTipService.ToolTip="TabIndex = 2"
                GettingFocus="Btn_GettingFocus"
                Margin="5"/>
    </StackPanel>
</Grid>

Navigation directionnelle 2D pour le clavier, le boîtier de commande et le contrôle à distance

Les types d’entrée non pointeurs, tels que le clavier, le boîtier de commande, le contrôle à distance et les outils d’accessibilité comme le Narrateur Windows, partagent un mécanisme sous-jacent commun pour naviguer et interagir avec l’interface utilisateur de votre application Windows.

Dans cette section, nous expliquons comment spécifier une stratégie de navigation par défaut et affiner la navigation au focus dans votre application via un ensemble de propriétés de stratégie de navigation qui prennent en charge tous les types d’entrée basés sur le focus et non pointeurs.

Pour plus d’informations générales sur la création d’applications et d’expériences pour Xbox/TV, consultez Interaction au clavier, Conception pour Xbox et TV, et Interactions avec le boîtier de commande et la commande à distance.

Les stratégies de navigation s’appliquent au clavier, au boîtier de commande, au contrôle à distance et à divers outils d’accessibilité.

Les propriétés de stratégie de navigation suivantes vous permettent d’influencer le contrôle qui reçoit le focus en fonction de la touche de direction, du bouton de pavé directionnel (D-pad) ou d’un appui similaire.

  • XYFocusUpNavigationStrategy
  • XYFocusDownNavigationStrategy
  • XYFocusLeftNavigationStrategy
  • XYFocusRightNavigationStrategy

Ces propriétés ont des valeurs possibles : Auto (valeur par défaut), NavigationDirectionDistance, Projection ou RectilinearDistance .

S’il est défini sur Auto, le comportement de l’élément est basé sur les ancêtres de l’élément. Si tous les éléments sont définis sur Auto, projection est utilisée.

Notes

D’autres facteurs, tels que l’élément précédemment ciblé ou la proximité de l’axe de la direction de navigation, peuvent influencer le résultat.

Projection

La stratégie Projection déplace le focus sur le premier élément rencontré lorsque le bord de l’élément actuellement ciblé est projeté dans le sens de la navigation.

Dans cet exemple, chaque direction de navigation du focus est définie sur Projection. Notez comment le focus passe de B1 à B4, en contournant B3. En effet, B3 n’est pas dans la zone de projection. Notez également comment un candidat au focus n’est pas identifié lors du déplacement à gauche de B1. En effet, la position de B2 par rapport à B1 élimine B3 comme candidat. Si B3 se trouvait sur la même ligne que B2, il serait un candidat viable pour la navigation à gauche. B2 est un candidat viable en raison de sa proximité non obstruée par rapport à l’axe de direction de navigation.

Stratégie de navigation par projection

Stratégie de navigation par projection

La stratégie NavigationDirectionDistance déplace le focus sur l’élément le plus proche de l’axe de la direction de navigation.

Le bord du rect englobant correspondant à la direction de navigation est étendu et projeté pour identifier les cibles candidates. Le premier élément rencontré est identifié en tant que cible. Dans le cas de plusieurs candidats, l’élément le plus proche est identifié comme cible. S’il y a encore plusieurs candidats, l’élément le plus haut/le plus à gauche est identifié comme candidat.

Stratégie de navigation NavigationDirectionDistance

Stratégie de navigation NavigationDirectionDistance

RectilinearDistance

La stratégie RectilinearDistance déplace le focus sur l’élément le plus proche en fonction de la distance rectiligne 2D (taxicab geometry).

La somme de la distance primaire et de la distance secondaire à chaque candidat potentiel est utilisée pour identifier la meilleure candidature. Dans une liaison, le premier élément à gauche est sélectionné si la direction demandée est vers le haut ou vers le bas, et le premier élément en haut est sélectionné si la direction demandée est à gauche ou à droite.

Stratégie de navigation RectilinearDistance

Stratégie de navigation RectilinearDistance

Cette image montre comment, lorsque B1 a le focus et que bas est la direction demandée, B3 est le candidat au focus RectilinearDistance. Ceci est basé sur les calculs suivants pour cet exemple :

  • La distance (B1, B3, Bas) est 10 + 0 = 10
  • La distance (B1, B2, Bas) est 0 + 40 = 30
  • La distance (B1, D, Bas) est 30 + 0 = 30