Compartilhar via


Acessibilidade do teclado

Se seu aplicativo não fornecer um bom acesso ao teclado, os usuários cegos ou com problemas de mobilidade poderão ter dificuldade para usá-lo ou talvez não consigam usá-lo.

Navegação pelo teclado entre elementos da interface do usuário

Para usar o teclado com um controle, o controle deve ter foco e, para receber o foco (sem usar um ponteiro), o controle deve estar acessível em um design de interface do usuário por meio da navegação por guias. Por padrão, a ordem de tabulação dos controles é a mesma em que eles são adicionados a uma superfície de design, listados em XAML ou adicionados programaticamente a um contêiner.

Na maioria dos casos, a ordem padrão com base em como você definiu controles em XAML é a melhor ordem, especialmente porque essa é a ordem em que os controles são lidos pelos leitores de tela. No entanto, a ordem padrão não corresponde necessariamente à ordem visual. A posição de exibição real pode depender do contêiner de layout pai e de certas propriedades que você pode definir nos elementos filho para influenciar o layout. Para ter certeza de que seu aplicativo tem uma boa ordem de tabulação, teste esse comportamento você mesmo. Especialmente se você tiver uma metáfora de grade ou metáfora de tabela para seu layout, a ordem em que os usuários podem ler versus a ordem de tabulação pode acabar diferente. Isso nem sempre é um problema em si. Mas apenas certifique-se de testar a funcionalidade do seu aplicativo como uma interface do usuário sensível ao toque e como uma interface do usuário acessível pelo teclado e verifique se a interface do usuário faz sentido de qualquer maneira.

Você pode fazer com que a ordem de tabulação corresponda à ordem visual ajustando o XAML. Ou você pode substituir a ordem de tabulação padrão definindo a propriedade TabIndex, conforme mostrado no exemplo a seguir de um layout de Grade que usa a navegação de guia coluna primeiro.

XAML

<!--Custom tab order.-->
<Grid>
  <Grid.RowDefinitions>...</Grid.RowDefinitions>
  <Grid.ColumnDefinitions>...</Grid.ColumnDefinitions>

  <TextBlock Grid.Column="1" HorizontalAlignment="Center">Groom</TextBlock>
  <TextBlock Grid.Column="2" HorizontalAlignment="Center">Bride</TextBlock>

  <TextBlock Grid.Row="1">First name</TextBlock>
  <TextBox x:Name="GroomFirstName" Grid.Row="1" Grid.Column="1" TabIndex="1"/>
  <TextBox x:Name="BrideFirstName" Grid.Row="1" Grid.Column="2" TabIndex="3"/>

  <TextBlock Grid.Row="2">Last name</TextBlock>
  <TextBox x:Name="GroomLastName" Grid.Row="2" Grid.Column="1" TabIndex="2"/>
  <TextBox x:Name="BrideLastName" Grid.Row="2" Grid.Column="2" TabIndex="4"/>
</Grid>

Talvez você queira excluir um controle da ordem de tabulação. Normalmente, você faz isso apenas tornando o controle não interativo, por exemplo, definindo sua propriedade IsEnabled como false. Um controle desabilitado é automaticamente excluído da ordem de tabulação. Mas, ocasionalmente, talvez você queira excluir um controle da ordem de tabulação, mesmo que ele não esteja desabilitado. Nesse caso, você pode definir a propriedade IsTabStop como false.

Todos os elementos que podem ter foco geralmente estão na ordem de tabulação por padrão. A exceção a isso é que certos tipos de exibição de texto, como RichTextBlock , podem ter foco para que possam ser acessados pela área de transferência para seleção de texto, no entanto, eles não estão na ordem de tabulação porque não é esperado que os elementos de texto estáticos estejam na ordem de tabulação. Eles não são convencionalmente interativos (não podem ser invocados e não exigem entrada de texto, mas oferecem suporte ao padrão de controle Texto que oferece suporte à localização e ao ajuste de pontos de seleção no texto). O texto não deve ter a conotação de que definir o foco para ele permitirá alguma ação possível. Os elementos de texto ainda serão detectados por tecnologias assistivas e lidos em voz alta em leitores de tela, mas isso depende de outras técnicas além de encontrar esses elementos na ordem prática de tabulação.

Se você ajustar os valores de TabIndex ou usar a ordem padrão, estas regras se aplicam:

  • Se TabIndex não estiver definido em um elemento, o valor padrão usado será Int32.MaxValue e a ordem de tabulação será baseada na ordem de declaração nas coleções XAML ou filho.
  • Se TabIndex estiver definido em um elemento:
    • Os elementos da interface do usuário com TabIndex igual a 0 são adicionados à ordem de tabulação com base na ordem de declaração em coleções XAML ou filhas.
    • Os elementos da interface do usuário com TabIndex maior que 0 são adicionados à ordem de tabulação com base no valor de TabIndex.
    • Os elementos da interface do usuário com TabIndex menor que 0 são adicionados à ordem de tabulação e aparecem antes de qualquer valor zero. Isso potencialmente difere do processamento do HTML de seu atributo tabindex (e tabindex negativo não era suportado em especificações HTML mais antigas).

Por exemplo, o trecho a seguir mostra uma coleção de elementos com configurações TabIndex variadas (B recebe o valor de Int32.MaxValue ou 2.147.483.647).

<StackPanel Background="#333">
  <StackPanel Background="#FF33FF">
    <Button>A</Button>
    <Button TabIndex="2147483647">B</Button>
    <Button>C</Button>
  </StackPanel>
  <StackPanel Background="#33FFFF">
    <Button TabIndex="1">D</Button>
    <Button TabIndex="1">E</Button>
    <Button TabIndex="0">F</Button>
  </StackPanel>
</StackPanel>

Isso resulta na seguinte ordem de tabulação:

  1. F
  2. D
  3. E
  4. A
  5. B
  6. C

Navegação pelo teclado entre seções proeminentes da interface do usuário

Embora a implementação da navegação por tabulação e teclado por si só possa fornecer uma interface do usuário compatível com acessibilidade, tornar uma interface do usuário acessível e utilizável geralmente requer mais algumas etapas. Normalmente, isso inclui:

  • Ouvindo F6 para navegar entre seções importantes da interface do usuário
  • Adicionando atalhos de teclado para ações comuns na interface do usuário
  • Adicionando chaves de acesso a controles importantes na interface do usuário

Consulte Atalhos de tecla abaixo e Teclas de acesso para obter mais orientações sobre como implementar atalhos e chaves de acesso.

Regiões de ciclismo da interface do usuário com F6

O F6 permite que os usuários de teclado naveguem entre as seções da interface do usuário sem, potencialmente, precisar percorrer dezenas de controles.

Por exemplo, pressionar F6 no Edge alternará entre a lista de guias, a barra de navegação/barra de aplicativos e o conteúdo da página da Web. Como uma página da Web potencialmente tem centenas de controles tabbable, isso facilita para os usuários do teclado acessar a lista de guias e a barra de navegação sem conhecer atalhos específicos. Isso também é útil em interfaces de usuário mais simples: a barra de tarefas do Windows percorre a tela inicial, a Pesquisa, a lista de aplicativos e partes da bandeja do sistema quando você pressiona F6.

O ciclo F6 geralmente corresponde a pontos de referência ou títulos acessíveis, embora não precise corresponder exatamente. F6 deve se concentrar em regiões grandes e distintas em sua interface do usuário, enquanto os pontos de referência podem ser mais granulares. Por exemplo, você pode marcar uma barra de aplicativos e sua caixa de pesquisa como pontos de referência, mas incluir apenas a própria barra de aplicativos no ciclo F6.

O XAML não implementa o ciclo F6; você mesmo precisará implementá-lo.

Se possível, porém, as regiões do ciclo F6 devem ter um nome acessível: por meio de um ponto de referência ou adicionando manualmente AutomationProperties.Name ao elemento "raiz" da região.

Normalmente, Shift-F6 deve circular na direção oposta.

Navegação pelo teclado em um elemento da interface do usuário

Para elementos compostos, é importante garantir uma navegação interna adequada entre os elementos contidos. Um elemento composto pode gerenciar seu filho ativo atual para reduzir a sobrecarga de ter todos os elementos filho capazes de ter foco. Esse elemento composto é incluído na ordem de tabulação e manipula os próprios eventos de navegação do teclado. Muitos dos controles compostos já têm alguma lógica de navegação interna embutida no tratamento de eventos do controle. Por exemplo, a travessia de teclas de seta de itens é habilitada por padrão nos controles ListView, GridView, ListBox e FlipView.

Alternativas de teclado para ações e eventos de ponteiro para elementos de controle específicos

Verifique se os elementos da interface do usuário que podem ser clicados também podem ser invocados usando o teclado. Para usar o teclado com um elemento de interface do usuário, o elemento deve ter foco. Somente as classes derivadas de Control oferecem suporte à navegação por foco e guia.

Para elementos da interface do usuário que podem ser invocados, implemente manipuladores de eventos de teclado para as teclas Barra de espaço e Enter. Isso torna o suporte básico à acessibilidade do teclado completo e permite que os usuários realizem cenários básicos de aplicativos usando apenas o teclado; ou seja, os usuários podem acessar todos os elementos interativos da interface do usuário e ativar a funcionalidade padrão.

Nos casos em que um elemento que você deseja usar na interface do usuário não pode ter foco, você pode criar seu próprio controle personalizado. Você deve definir a propriedade IsTabStop como true para habilitar o foco e deve fornecer uma indicação visual do estado focado criando um estado visual que decore a interface do usuário com um indicador de foco. No entanto, geralmente é mais fácil usar a composição de controle para que o suporte para paradas de tabulação, foco e pares e padrões de automação da interface do usuário da Microsoft sejam manipulados pelo controle no qual você escolhe compor seu conteúdo.

Por exemplo, em vez de manipular um evento pressionado por ponteiro em uma Imagem, você pode encapsular esse elemento em um Button para obter suporte a ponteiro, teclado e foco.

XAML

<!--Don't do this.-->
<Image Source="sample.jpg" PointerPressed="Image_PointerPressed"/>

<!--Do this instead.-->
<Button Click="Button_Click"><Image Source="sample.jpg"/></Button>

Atalhos do teclado

Além de implementar a navegação e a ativação do teclado para seu aplicativo, é uma boa prática implementar atalhos para a funcionalidade do aplicativo. A navegação por guias fornece um bom nível básico de suporte ao teclado, mas com formulários complexos, você também pode querer adicionar suporte para teclas de atalho. Isso pode tornar seu aplicativo mais eficiente de usar, mesmo para pessoas que usam um teclado e dispositivos apontadores.

Um atalho é uma combinação de teclado que aumenta a produtividade, fornecendo uma maneira eficiente para o usuário acessar a funcionalidade do aplicativo. Existem dois tipos de atalhos:

  • Uma tecla de acesso é um atalho para uma parte da interface do usuário em seu aplicativo. As teclas de acesso consistem na tecla Alt mais uma tecla de letra.
  • Uma tecla aceleradora é um atalho para um comando de aplicativo. Seu aplicativo pode ou não ter interface do usuário que corresponde exatamente ao comando. As teclas de aceleração consistem na tecla Ctrl mais uma tecla de letra.

É imprescindível que você forneça uma maneira fácil para os usuários que dependem de leitores de tela e outras tecnologias assistivas descobrirem as teclas de atalho do seu aplicativo. Comunique teclas de atalho usando dicas de ferramentas, nomes acessíveis, descrições acessíveis ou alguma outra forma de comunicação na tela. No mínimo, as teclas de atalho devem estar bem documentadas no conteúdo da Ajuda do seu aplicativo.

Você pode documentar chaves de acesso por meio de leitores de tela definindo a propriedade anexada AutomationProperties.AccessKey como uma cadeia de caracteres que descreve a tecla de atalho. Há também uma propriedade anexada AutomationProperties.AcceleratorKey para documentar teclas de atalho não mnemônicas, embora os leitores de tela geralmente tratem ambas as propriedades da mesma maneira. Tente documentar as teclas de atalho de várias maneiras, usando dicas de ferramentas, propriedades de automação e documentação de Ajuda escrita.

O exemplo a seguir demonstra como documentar teclas de atalho para reprodução de mídia, pausa e botões de parada.

XAML

<Grid KeyDown="Grid_KeyDown">

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>

  <MediaElement x:Name="DemoMovie" Source="xbox.wmv"
    Width="500" Height="500" Margin="20" HorizontalAlignment="Center" />

  <StackPanel Grid.Row="1" Margin="10"
    Orientation="Horizontal" HorizontalAlignment="Center">

    <Button x:Name="PlayButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+P"
      AutomationProperties.AcceleratorKey="Control P">
      <TextBlock>Play</TextBlock>
    </Button>

    <Button x:Name="PauseButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+A"
      AutomationProperties.AcceleratorKey="Control A">
      <TextBlock>Pause</TextBlock>
    </Button>

    <Button x:Name="StopButton" Click="MediaButton_Click"
      ToolTipService.ToolTip="Shortcut key: Ctrl+S"
      AutomationProperties.AcceleratorKey="Control S">
      <TextBlock>Stop</TextBlock>
    </Button>
  </StackPanel>
</Grid>

Importante

Definir o AutomationProperties.AcceleratorKey ou AutomationProperties.AccessKey não habilita a funcionalidade do teclado. Ele apenas informa à estrutura de Automação da Interface do Usuário quais chaves devem ser usadas, para que essas informações possam ser repassadas aos usuários por meio de tecnologias assistivas. A implementação para manipulação de chaves ainda precisa ser feita em código, não em XAML. Você ainda precisará anexar manipuladores para eventos KeyDown ou KeyUp no controle relevante para realmente implementar o comportamento de atalho de teclado em seu aplicativo. Além disso, a decoração de texto sublinhado para uma chave de acesso não é fornecida automaticamente. Você deve sublinhar explicitamente o texto da chave específica em seu mnemônico como formatação de sublinhado embutido se desejar mostrar o texto sublinhado na interface do usuário.

Para simplificar, o exemplo anterior omite o uso de recursos para cadeias de caracteres como "Ctrl+A". No entanto, você também deve considerar as teclas de atalho durante a localização. A localização de teclas de atalho é relevante porque a escolha da tecla a ser usada como tecla de atalho normalmente depende do rótulo de texto visível do elemento.

Para obter mais orientações sobre como implementar teclas de atalho, consulte Teclas de atalho nas Diretrizes de interação da experiência do usuário do Windows.

Implementando um manipulador de eventos de chave

Os eventos de entrada, como os eventos-chave, usam um conceito de evento chamado eventos roteados. Um evento roteado pode borbulhar através dos elementos filho de um controle composto, de modo que um pai de controle comum pode manipular eventos para vários elementos filho. Esse modelo de evento é conveniente para definir ações de tecla de atalho para um controle que contém várias partes compostas que, por design, não podem ter foco ou fazer parte da ordem de tabulação.

Para obter um código de exemplo que mostra como escrever um manipulador de eventos de chave que inclui a verificação de modificadores como a tecla Ctrl, consulte Interações do teclado.

Navegação pelo teclado para controles personalizados

Recomendamos o uso de teclas de seta como atalhos de teclado para navegar entre elementos filho, nos casos em que os elementos filho têm uma relação espacial entre si. Se os nós de exibição em árvore tiverem subelementos separados para lidar com a ativação de expandir-recolher e de nós, use as teclas de seta para a esquerda e para a direita para fornecer a funcionalidade de expandir e recolher do teclado. Se você tiver um controle orientado que ofereça suporte à travessia direcional dentro do conteúdo do controle, use as teclas de seta apropriadas.

Geralmente, você implementa manipulação de chave personalizada para controles personalizados incluindo uma substituição dos métodos OnKeyDown e OnKeyUp como parte da lógica de classe.

Um exemplo de um estado visual para um indicador de foco

Mencionamos anteriormente que qualquer controle personalizado que permita ao usuário focalizá-lo deve ter um indicador de foco visual. Normalmente, esse indicador de foco é tão simples quanto desenhar uma forma de retângulo imediatamente ao redor do retângulo delimitador normal do controle. O Rectangle para foco visual é um elemento de mesmo nível para o restante da composição do controle em um modelo de controle, mas é inicialmente definido com um valor de Visibilidade de Collapsed porque o controle ainda não está focado. Em seguida, quando o controle obtém foco, um estado visual é invocado que define especificamente a visibilidade do visual de foco como visível. Depois que o foco é movido para outro lugar, outro estado visual é chamado e a Visibilidade torna-se Recolhida.

Todos os controles XAML padrão exibirão um indicador de foco visual apropriado quando focados (se puderem ser focados). Há também aparências potencialmente diferentes dependendo do tema selecionado pelo usuário (especialmente se o usuário estiver usando um modo de alto contraste). Se você estiver usando os controles XAML em sua interface do usuário e não substituir os modelos de controle, não precisará fazer nada extra para obter indicadores de foco visual em controles que se comportam e são exibidos corretamente. Mas se você pretende remodelar um controle ou se está curioso sobre como os controles XAML fornecem seus indicadores de foco visual, o restante desta seção explica como isso é feito em XAML e na lógica de controle.

Aqui está um exemplo de XAML que vem do modelo XAML padrão para um Button.

XAML

<ControlTemplate TargetType="Button">
...
    <Rectangle
      x:Name="FocusVisualWhite"
      IsHitTestVisible="False"
      Stroke="{ThemeResource FocusVisualWhiteStrokeThemeBrush}"
      StrokeEndLineCap="Square"
      StrokeDashArray="1,1"
      Opacity="0"
      StrokeDashOffset="1.5"/>
    <Rectangle
      x:Name="FocusVisualBlack"
      IsHitTestVisible="False"
      Stroke="{ThemeResource FocusVisualBlackStrokeThemeBrush}"
      StrokeEndLineCap="Square"
      StrokeDashArray="1,1"
      Opacity="0"
      StrokeDashOffset="0.5"/>
...
</ControlTemplate>

Até agora esta é apenas a composição. Para controlar a visibilidade do indicador de foco, defina estados visuais que alternam a propriedade Visibilidade . Isso é feito usando o VisualStateManager e a propriedade anexada VisualStateManager.VisualStateGroups, conforme aplicado ao elemento raiz que define a composição.

XAML

<ControlTemplate TargetType="Button">
  <Grid>
    <VisualStateManager.VisualStateGroups>
       <!--other visual state groups here-->
       <VisualStateGroup x:Name="FocusStates">
         <VisualState x:Name="Focused">
           <Storyboard>
             <DoubleAnimation
               Storyboard.TargetName="FocusVisualWhite"
               Storyboard.TargetProperty="Opacity"
               To="1" Duration="0"/>
             <DoubleAnimation
               Storyboard.TargetName="FocusVisualBlack"
               Storyboard.TargetProperty="Opacity"
               To="1" Duration="0"/>
         </VisualState>
         <VisualState x:Name="Unfocused" />
         <VisualState x:Name="PointerFocused" />
       </VisualStateGroup>
     <VisualStateManager.VisualStateGroups>
<!--composition is here-->
   </Grid>
</ControlTemplate>

Observe como apenas um dos estados nomeados ajusta a Visibilidade diretamente, enquanto os outros estão aparentemente vazios. A maneira como os estados visuais funcionam é que, assim que o controle usa outro estado do mesmo VisualStateGroup, todas as animações aplicadas pelo estado anterior são imediatamente canceladas. Como a Visibilidade padrão da composição é Recolhida, isso significa que o retângulo não será exibido. A lógica de controle controla isso ouvindo eventos de foco como GotFocus e alterando os estados com GoToState. Muitas vezes, isso já é manipulado para você se você estiver usando um controle padrão ou personalizando com base em um controle que já tem esse comportamento.

Acessibilidade do teclado e Windows Phone

Um dispositivo Windows Phone normalmente não tem um teclado de hardware dedicado. No entanto, um SIP (Soft Input Panel) pode oferecer suporte a vários cenários de acessibilidade do teclado. Os leitores de tela podem ler a entrada de texto do SIP de texto, incluindo o anúncio de exclusões. Os usuários podem descobrir onde estão seus dedos porque o leitor de tela pode detectar que o usuário está examinando as teclas e lê o nome da chave digitalizada em voz alta. Além disso, alguns dos conceitos de acessibilidade orientada ao teclado podem ser mapeados para comportamentos relacionados à tecnologia assistiva que não usam um teclado. Por exemplo, mesmo que um SIP não inclua uma tecla Tab, o Narrador oferece suporte a um gesto de toque equivalente a pressionar a tecla Tab, portanto, ter uma ordem de tabulação útil através dos controles em uma interface do usuário ainda é um princípio de acessibilidade importante. As teclas de seta usadas para navegar nas partes dentro de controles complexos também são suportadas por meio de gestos de toque do Narrador. Quando o foco atinge um controle que não é para entrada de texto, o Narrador oferece suporte a um gesto que invoca a ação desse controle.

Os atalhos de teclado normalmente não são relevantes para aplicativos do Windows Phone, porque um SIP não inclui as teclas Control ou Alt.

Exemplos

Dica

O aplicativo Galeria da WinUI 3 inclui exemplos interativos da maioria dos controles, recursos e funcionalidades da WinUI 3. Obtenha o aplicativo na Microsoft Store ou o código-fonte no GitHub