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


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

Клавиатура, удаленная и D-панель

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

Обзор

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

Примечание.

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

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

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

Инструкции по созданию пользовательских интерфейсов в приложениях Windows для указателя см. в разделе "Ввод указателя на обработчик".

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

Общее руководство

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

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

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

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

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

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

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

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

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

Примечание.

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

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

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

Отключен

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

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

В этом примере основной объект StackPanel (ContainerPrimary) имеет значение XYFocusKeyboardNavigation в значение Enabled. Все дочерние элементы наследуют этот параметр и можно перейти к ним с помощью клавиш со стрелками. Однако элементы 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 значение Enabled для поддержки 2D-направления навигации для элемента управления и каждого из дочерних объектов UIElement.

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

Поведение XYFocusKeyboardNavigationПоведение XYFocusKeyboardNavigation

В этом примере основной объект StackPanel (ContainerPrimary) имеет значение XYFocusKeyboardNavigation в значение Enabled. Все дочерние элементы наследуют этот параметр и можно перейти к ним с помощью клавиш со стрелками. Элементы 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 и IsTabStop true), а порядок логических вкладок, производный от макета элемента управления в приложении. Однако порядок по умолчанию не обязательно соответствует визуальному порядку. Фактическое положение отображения может зависеть от родительского контейнера макета и определенных свойств, которые можно задать на дочерних элементах, чтобы повлиять на макет.

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

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

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

Свойство 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) или аналогичного нажатия.

  • XYFocusUpNavigationStrategy
  • XYFocusDownNavigationStrategy
  • XYFocusLeftNavigationStrategy
  • XYFocusRightNavigationStrategy

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

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

Примечание.

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

Проекция

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

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

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

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

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

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

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

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

RectilinearDistance

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

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

Стратегия навигации RectilinearDistance

Стратегия навигации RectilinearDistance

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

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