Elemento Focável Aninhado
Não roube o foco de um elemento pai clicável tornando um elemento filho focável
O Que Verificamos
Elementos focáveis não devem estar aninhados dentro de elementos pais clicáveis. Quando um elemento filho não interativo é focável, a tecnologia assistiva foca nele em vez do pai clicável — o que significa que o papel interativo do elemento nunca é anunciado.
Esta regra verifica todos os controles focáveis em termos de acessibilidade que não são interativos por si mesmos. Se tal controle estiver contido em um elemento pai clicável, ele é inerentemente interativo, mas não anunciará um papel. O elemento será sinalizado como uma violação de acessibilidade.
Exemplo de Falha ❌
O cartão é clicável, mas a foto do perfil dentro dele é focável separadamente.
TalkBack não anuncia o papel do cartão ou a dica de "Toque duas vezes para ativar", e em vez disso foca e anuncia o elemento interno.
Os usuários não sabem que o cartão é interativo, e o elemento com foco não é clicável.
Exemplo de Sucesso ✅
O elemento interno não é mais focável separadamente.
TalkBack foca no próprio cartão e anuncia seu conteúdo, papel e "Toque duas vezes para ativar".
Os usuários entendem que o cartão é interativo e podem ativá-lo.
Em Resumo
- Esta regra tem um impacto Crítico para usuários do TalkBack e do Voice Access
- Quando um elemento filho rouba o foco de um pai clicável, o papel interativo é perdido
- O TalkBack não anunciará "Toque duas vezes para ativar" se o elemento focado não for ele mesmo clicável
- A solução é sempre remover a focabilidade do elemento aninhado, e não adicionar um papel a ele
- Visualizações de contêineres que não têm ação não devem ser deixadas clicáveis — isso evita falsos positivos
Impacto para os Usuários
Quando a tecnologia assistiva não anuncia um papel, usuários cegos ou com baixa visão que dependem do TalkBack não saberão que podem disparar uma ação. Por exemplo, o TalkBack foca em um elemento interno e anuncia apenas seu texto (ex.: "Tema"). Ele não anuncia que é um botão, ou que o usuário deve tocar duas vezes para ativar. Os usuários ficam sem o contexto necessário para interagir com a tela.
Confirmar Problema de Elemento Focável Aninhado
- Ative o TalkBack
- Foque no elemento e em cada um de seus descendentes
- Uma das seguintes coisas acontecerá:
- Inacessível: O TalkBack lê o texto mas não anuncia um papel ou capacidade de interação
- Acessível: O TalkBack lê todo o texto e também anuncia um papel e/ou como interagir com o elemento
Corrigir Problemas
Remova a focabilidade de elementos aninhados para que o pai clicável possa ganhar foco e anunciar seu papel. Não adicione propriedades focáveis a descendentes não interativos de uma visualização clicável.
Para evitar um falso positivo, certifique-se de que elementos contêiner que não fazem nada quando tocados não sejam deixados clicáveis. Nossas ferramentas não podem determinar se um elemento clicável tem uma ação programada associada, então devemos assumir que sim, a fim de sinalizar um comportamento potencialmente inacessível.
Examine elementos contêiner circundantes, como Frame Layouts, Card Views ou Gavetas, para garantir que qualquer elemento sem uma ação associada não seja configurado como clicável.
XML
No exemplo abaixo, o MaterialCardView é clicável, mas se uma das crianças - LinearLayout ou TextView - tiver focusable="true", o TalkBack focará nela em vez do cartão. Em seu estado padrão, a propriedade focusable de ambos LinearLayout e TextView é falsa. Certifique-se de que não está configurada como verdadeira, para que o cartão possa ganhar foco e anunciar seu papel interativo.
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/contact_name"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>Compose
Neste exemplo, o Card é clicável, mas se uma das crianças - Row ou Text - tiver um atributo .focusable(), o TalkBack focará nela em vez disso. Certifique-se de que Row ou Text não tenha um atributo .focusable(), para que o Card possa ganhar foco, anunciar seu conteúdo de texto e transmitir seu papel interativo (ex.:"Toque duas vezes para ativar").
Card(
modifier = Modifier
.clickable {
openContact(context)
}
) {
Row(
modifier = Modifier
.padding(10.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally)
) {
Text("Sarah Anderson")
}
}.NET MAUI
No exemplo abaixo, o cartão de contato Grid tem um TapGestureRecognizer para abrir o contato. Se um elemento filho dentro do Grid for focável independentemente, o TalkBack focará nele em vez do cartão. Certifique-se de que nenhum elemento filho tenha AutomationProperties.IsInAccessibleTree="true" configurado explicitamente, para que o Grid mantenha o foco e possa anunciar "Toque duas vezes para ativar".
<Grid
HorizontalOptions="FillAndExpand"
RowDefinitions="Auto,Auto"
RowSpacing="10"
VerticalOptions="FillAndExpand">
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OpenContactCommand}"/>
</Grid.GestureRecognizers>
<Label
Grid.Row="1"
FontAttributes="Bold"
FontSize="16"
HorizontalOptions="CenterAndExpand"
VerticalOptions="FillAndExpand">
<Label.FormattedText>
<FormattedString>
<Span Text="Sarah Anderson"/>
</FormattedString>
</Label.FormattedText>
</Label>
</Grid>React Native
Neste exemplo, o cartão de contato é um TouchableOpacity com propriedades de acessibilidade configuradas diretamente nele. As propriedades accessible={true} e accessibilityRole="button" garantem que o TalkBack anuncie o cartão como um elemento interativo. Nenhuma visualização filha dentro dele deve ter accessible={true} configurado de forma independente, o que faria com que elas roubassem o foco do cartão.
<TouchableOpacity
accessible={true}
accessibilityRole="button"
style={styles.contactCard}
onPress={() => openContact("sarah-anderson")}
>
<Text>Sarah Anderson</Text>
<Text>sarah@example.com</Text>
</TouchableOpacity>Flutter
Neste exemplo, o cartão de contato é um Card com um InkWell lidando com o toque. Se um widget filho dentro do Card tiver seu próprio Semantics envolvente com button: true ou onTap configurado, o TalkBack focará nele em vez do cartão. Mantenha o manipulador de toque no InkWell e certifique-se de que nenhum widget descendente reivindique foco de forma independente.
Card(
child: InkWell(
onTap: () => openContact(context, "sarah-anderson"),
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Sarah Anderson"),
Text("sarah@example.com"),
],
),
),
),
)Posso Ignorar Esta Regra?
Elemento Focável Aninhado tem um impacto crítico para os usuários, e recomendamos fortemente corrigir este problema. Quando o foco está em um elemento não interativo dentro de um pai clicável, os usuários do TalkBack não têm como saber que o elemento pode ser ativado. Ignorar esta regra significa que esses usuários efetivamente não podem interagir com o elemento afetado. Saiba mais sobre regras de ignorar.
Recursos
Páginas do Curso da Deque University
Nota: Acesso completo aos recursos da Deque University requer uma assinatura.
Outros Recursos
- Diretrizes de Acessibilidade para Conteúdo Web (WCAG) 2.1, Recomendação W3C
- Documentos de Compreensão do WCAG 2.1
