Поделиться через


Навигация фокуса для клавиатуры, геймпада, пульта дистанционного управления и средств специальных возможностей

клавиатура, пульт и D-пад

Используйте навигацию фокуса, чтобы обеспечить комплексный и согласованный интерфейс взаимодействия в приложениях Windows и пользовательских элементах управления для пользователей с клавиатурой, с ограниченными возможностями и другими требованиями к специальным возможностям, а также 10-футовый интерфейс телевизионных экранов и Xbox One.

Обзор

Навигация фокуса относится к базовому механизму, который позволяет пользователям перемещаться и взаимодействовать с пользовательским интерфейсом приложения Windows с помощью клавиатуры, геймпада или удаленного управления.

Замечание

Устройства ввода обычно классифицируются как указывающие устройства, такие как сенсорный ввод, сенсорный панель, перо и мышь, а также не указывающие устройства, такие как клавиатура, геймпад и удаленный контроль.

В этом разделе описывается, как оптимизировать приложение Windows и создавать индивидуальные сценарии взаимодействия для пользователей, использующих типы ввода, не использующие указатель.

Несмотря на то что мы сосредотачиваемся на вводе с клавиатуры для специальных элементов управления в приложениях Windows на ПК, хорошо организованная работа с клавиатурой также важна для программных клавиатур, таких как сенсорная клавиатура и экранная клавиатура (OSK), поддерживающие инструменты специальных возможностей, такие как Экранный диктор Windows, и возможность работы с интерфейсом, рассчитанным на просмотр с расстояния 10 футов.

Руководство по созданию индивидуальных возможностей в приложениях Windows для указательных устройств смотрите в разделе Ввод указателя.

Дополнительные сведения о создании приложений и интерфейсов для клавиатуры см. в .

Общие рекомендации

Только те элементы пользовательского интерфейса, которые требуют взаимодействия с пользователем, должны поддерживать навигацию фокуса, элементы, которые не требуют действия, например статические изображения, не требуют фокуса клавиатуры. Программы чтения с экрана и аналогичные инструменты для обеспечения доступности по-прежнему сообщают о наличии этих статических элементов, даже если они не включены в переключение фокуса.

Важно помнить, что в отличие от навигации с помощью указателя устройства, например мыши или сенсорного ввода, навигация фокуса является линейной. При реализации навигации фокуса учтите, как пользователь будет взаимодействовать с вашим приложением и какой должна быть логическая навигация. В большинстве случаев мы рекомендуем, чтобы настроенное поведение навигации фокуса соответствовало предпочтительному шаблону чтения культуры пользователя.

Ниже приведены некоторые другие рекомендации по навигации фокуса.

  • Группируются ли элементы управления логически?
  • Существуют ли группы элементов управления с большей важностью?
    • Если да, содержат ли эти группы подгруппы?
  • Требуется ли для макета настраиваемая навигация (клавиши со стрелками) и порядок вкладок?

Программное обеспечение для доступности из электронной книги включает в себя отличную главу по проектированию логической иерархии .

2D-направление навигации для клавиатуры

2D-область внутренней навигации элемента или группы управления называется его «направляющей зоной». Когда фокус перемещается на этот объект, клавиши со стрелками на клавиатуре (влево, вправо, вверх и вниз) можно использовать для перехода между дочерними элементами в заданном направлении.

направленная область 2D внутренняя область навигации или направленная область группы управления

Можно использовать свойство XYFocusKeyboardNavigation (которое имеет возможные значения авто, включеноили Отключено) для управления 2D-внутренней навигацией с помощью клавиш со стрелками клавиатуры.

Замечание

Порядок вкладок не влияет на это свойство. Чтобы избежать запутанной навигации, рекомендуется, чтобы дочерние элементы области направления , а не, были явно указаны в порядке навигации с помощью табуляции в вашем приложении. Дополнительные сведения о поведении табуляции элемента см. в свойствах UIElement.TabFocusNavigation и TabIndex .

Автоматическое (поведение по умолчанию)

Если задано значение Auto, поведение направленной навигации определяется происхождением элемента или иерархией наследования. Если все предки находятся в режиме по умолчанию (для параметра Авто), навигация по направлению с помощью клавиатуры не поддерживается.

Отключен

Задайте XYFocusKeyboardNavigation в Отключено, чтобы заблокировать направленное перемещение к элементу управления и его дочерним элементам.

режим отключенной навигации XYFocusKeyboard режим отключенной навигации XYFocusKeyboard

В этом примере для основного StackPanel (ContainerPrimary) XYFocusKeyboardNavigation установлено значение Включено. Все дочерние элементы наследуют этот параметр и можно перейти к ним с помощью клавиш со стрелками. Однако элементы B3 и B4 находятся в дополнительном StackPanel (ContainerSecondary) с XYFocusKeyboardNavigation значение Отключено, что переопределяет основной контейнер и отключает навигацию со стрелками для себя и между его дочерними элементами.

<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>

Включено

Задайте XYFocusKeyboardNavigation включено для поддержки 2D-навигации по элементу управления и каждому из дочерних объектов UIEl ement.

При установке навигация с клавишами со стрелками ограничена элементами в области направления. Навигация по вкладкам не затрагивается, так как все элементы управления остаются доступными с помощью иерархии порядка вкладок.

поведение с включенной функцией XYFocusKeyboardNavigation поведение с включенной функцией XYFocusKeyboardNavigation

В этом примере для основного StackPanel (ContainerPrimary) XYFocusKeyboardNavigation установлено значение Включено. Все дочерние элементы наследуют этот параметр и можно перейти к ним с помощью клавиш со стрелками. Элементы B3 и B4 находятся в дополнительном StackPanel (ContainerSecondary), где XYFocusKeyboardNavigation не задан, и поэтому он наследует настройки основного контейнера. Элемент B5 не находится в объявленной области направления и не поддерживает навигацию со стрелками, но поддерживает стандартное поведение навигации на вкладках.

<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>

Вы можете иметь несколько уровней вложенных областей направлений. Если у всех родительских элементов параметр XYFocusKeyboardNavigation установлен на Значение "Включено", границы внутренних областей навигации игнорируются.

Ниже приведен пример двух вложенных областей направления в элементе, который явно не поддерживает 2D-навигацию. В этом случае навигация между двумя вложенными областями не поддерживается.

включено и вложенное поведение XYFocusKeyboardNavigation включено и вложенное поведение XYFocusKeyboardNavigation

Ниже приведен более сложный пример трех вложенных направленных областей, где:

  • Когда B1 в фокусе, можно перейти только к B5 (и наоборот), так как существует граница направления с установкой XYFocusKeyboardNavigation в значение Disabled, что делает B2, B3 и B4 недоступными с помощью клавиш со стрелками
  • Когда фокус находится на B2, можно перейти только к B3 (и наоборот), так как граница направления не позволяет использовать стрелки для навигации к B1, B4 и B5.
  • При фокусе B4 клавиша TAB должна использоваться для перехода между элементами управления

функция XYFocusKeyboardNavigation включена и сложное вложенное поведение

включена функция XYFocusKeyboardNavigation и сложное вложенное поведение

Навигация по вкладкам

Хотя клавиши со стрелками можно использовать для 2D-навигации с помощью элемента управления или группы элементов управления, клавиша TAB может использоваться для перехода между всеми элементами управления в приложении Windows.

Все интерактивные элементы управления по умолчанию поддерживают навигацию с помощью клавиши Tab (IsEnabled и свойство IsTabStoptrue), а порядок логических вкладок определяется макетом контроля в приложении. Однако порядок по умолчанию не обязательно соответствует визуальному порядку. Фактическое положение элемента отображения может зависеть от родительского контейнера расположения и определенных свойств, которые можно задать для дочерних элементов, чтобы повлиять на расположение.

Избегайте настраиваемого порядка вкладок, из-за которого фокус перемещается по вашему приложению. Например, список элементов управления в форме должен иметь порядок вкладок, который перемещается сверху вниз и слева направо (в зависимости от языкового стандарта).

В этом разделе описано, как этот порядок вкладок можно полностью настроить в соответствии с вашим приложением.

Настройка поведения навигации на вкладке

Свойство tabFocusNavigation UIElement указывает поведение перемещения по вкладкам для всего дерева объектов (или направленной области).

Замечание

Используйте это свойство вместо свойства Control.TabNavigation для объектов, которые не используют ControlTemplate для определения их внешнего вида.

Как упоминалось в предыдущем разделе, чтобы избежать запутанной навигации, следует, чтобы дочерние элементы области направления , а не, были явно указаны в порядке навигации по вкладкам вашего приложения. См. свойства UIElement.TabFocusNavigation и TabIndex для получения дополнительной информации о поведении табуляции элемента.

Для версий старше, чем Windows 10 Creators Update (сборка 10.0.15063), настройки вкладок ограничивались объектами ControlTemplate. Дополнительные сведения см. в разделе Control.TabNavigation.

TabFocusNavigation имеет значение типа KeyboardNavigationMode со следующими возможными значениями (обратите внимание, что эти примеры не являются настраиваемыми группами элементов управления и не требуют внутренней навигации с помощью клавиш со стрелками):

  • локальные индексы табуляции (по умолчанию) распознаются в локальном поддереве внутри контейнера. В этом примере порядок вкладок — B1, B2, B3, B4, B5, B6, B7, B1.

    поведение навигации на вкладке

    поведение навигации на вкладке "Локальный"

  • После контейнер и все дочерние элементы получают фокус один раз. В этом примере порядок вкладок — B1, B2, B7, B1 (внутренняя навигация со стрелкой также демонстрируется).

    режим навигации на вкладке

    поведение навигации на вкладке "Один раз"

  • цикл
    Фокус возвращается к начальному фокусируемому элементу внутри контейнера. В этом примере порядок вкладок — B1, B2, B3, B4, B5, B6, B2...

    Поведение навигации на вкладке

    Поведение навигации на вкладке "Цикл"

Ниже приведен код для предыдущих примеров (с 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

Используйте TabIndex , чтобы указать порядок, в котором элементы получают фокус при переходе пользователя через элементы управления с помощью клавиши TAB. Элемент управления с более низким индексом табуляции получает фокус перед элементом управления с более высоким индексом.

Если элемент управления не имеет указанного значения TabIndex, ему назначается значение индекса, более высокое, чем текущее наибольшее значение индекса (и самый низкий приоритет) всех интерактивных элементов управления в визуальном дереве, в зависимости от области.

Все дочерние элементы элемента управления считаются областью, и если один из этих элементов также содержит дочерние элементы, они считаются другой областью. Любая неоднозначность разрешается путем выбора первого элемента в визуальном дереве области.

Чтобы исключить элемент управления из порядка вкладок, задайте для свойства IsTabStopзначение false.

Переопределите порядок вкладок по умолчанию, задав свойство TabIndex .

Замечание

TabIndex работает так же, как с UIElement.TabFocusNavigation и Control.TabNavigation.

Здесь мы покажем, как свойство TabIndex может влиять на навигацию фокуса для определенных элементов.

навигация по вкладке

навигация по вкладке "Локальная" с учетом поведения TabIndex

В предыдущем примере существует две области:

  • B1, направленное пространство (B2 - B6) и B7
  • направление (B2 - B6)

Когда элемент B3 (в зоне направления) получает фокус, область фокуса изменяется, и навигация по вкладкам переносится в зону направления, где определяется лучший кандидат для следующего фокуса. В этом случае за B2 следует B4, B5 и B6. Затем область снова изменяется, и фокус перемещается на B1.

Ниже приведен код для этого примера.

<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>

2D-направление навигации для клавиатуры, геймпада и удаленного управления

Неуказательные типы входных данных, такие как клавиатура, геймпад, пульт дистанционного управления, а также средства доступности, например экранный диктор Windows, используют общий базовый механизм навигации и взаимодействия с пользовательским интерфейсом вашего приложения Windows.

В этом разделе описано, как указать предпочтительную стратегию навигации и настроить навигацию фокуса в приложении с помощью набора свойств стратегии навигации, поддерживающих все типы входных данных, отличные от указателя.

Дополнительные сведения о создании приложений и возможностей для Xbox/TV см. в взаимодействии с клавиатурой, проектировании для Xbox и телевизора, а также взаимодействии с геймпадом и пультом дистанционного управления.

Стратегии навигации применимы к клавиатуре, геймпаду, удаленному управлению и различным средствам специальных возможностей.

Следующие свойства стратегии навигации позволяют влиять на то, какой элемент управления получает фокус в зависимости от нажатия клавиши со стрелкой, джойстика (D-pad) или другого аналогичного устройства.

  • СтратегияНавигацииXYФокусНаверх
  • XYFocusDownNavigationStrategy
  • XYFocusLeftNavigationStrategy
  • XYFocusRightNavigationStrategy (Стратегия навигации вправо XYFocus)

Эти свойства имеют возможные значения Авто (по умолчанию), NavigationDirectionDistance, проекцииили RectilinearDistance .

Если задано значение Auto, поведение элемента основано на предках элемента. Если для всех элементов задано значение Авто, используется Проекция.

Замечание

Другие факторы, такие как ранее ориентированный элемент или близость к оси направления навигации, могут повлиять на результат.

Проекция

Стратегия проекции перемещает фокус на первый элемент, возникший, когда край текущего фокусируемого элемента проецируется в направлении навигации.

В этом примере для каждого направления навигации фокуса задано значение Проекция. Обратите внимание, как фокус перемещается с B1 на B4, обходя B3. Это связано с тем, что B3 не находится в зоне проекции. Кроме того, обратите внимание, что кандидат фокуса не определяется при перемещении влево от B1. Это связано с тем, что позиция B2 относительно B1 исключает B3 в качестве кандидата. Если B3 был в том же ряду, что и B2, это будет подходящим кандидатом для левой навигации. B2 является жизнеспособным кандидатом из-за его непрепятственной близости к оси направления навигации.

Стратегия навигации проекции

стратегия навигации проекции

Стратегия NavigationDirectionDistance перемещает фокус на элемент, ближайший к оси направления навигации.

Край ограничивающего прямоугольника, соответствующего направлению навигации, расширен и проецирован для определения целевых объектов-кандидатов. Первый обнаруженный элемент определяется как целевой объект. В случае нескольких кандидатов ближайший элемент определяется как целевой объект. Если есть еще несколько кандидатов, самый верхний или левый элемент определяется как кандидат.

стратегия навигации NavigationDirectionDistance

стратегия навигации NavigationDirectionDistance

Дистанция по прямой

Стратегия RectilinearDistance перемещает фокус на ближайший элемент на основе 2D-прямоугольного расстояния (геометрии Taxicab).

Сумма первичного расстояния и дополнительного расстояния к каждому потенциальному кандидату используется для определения лучшей кандидатуры. При равенстве первый элемент слева выбирается, если запрошенное направление вверх или вниз, а первый элемент сверху выбирается, если запрошенное направление слева или справа.

стратегия навигации ПрямолинейноеРасстояние

стратегия навигации "RectilinearDistance"

На этом изображении показано, что когда фокус находится на B1, а запрошенное направление вниз, кандидатом фокуса по RectilinearDistance является B3. Это основано на следующих вычислениях для этого примера:

  • Расстояние (B1, B3, Down) равно 10 + 0 = 10
  • Расстояние (B1, B2, Down) равно 0 + 40 = 30
  • Расстояние (B1, D, Down) составляет 30 + 0 = 30