Elemento Enfocable Anidado
No le quite el enfoque a un elemento padre clicable haciendo que un elemento hijo sea enfocable
Qué Verificamos
Los elementos enfocados no deben estar anidados dentro de elementos padres clicables. Cuando un elemento hijo no interactivo es enfocable, la tecnología de asistencia se enfoca en él en lugar del padre clicable, lo que significa que el papel interactivo del elemento nunca se anuncia.
Esta regla verifica todos los controles accesibles por el enfoque que no son interactivos por sí mismos. Si dicho control se encuentra dentro de un padre clicable, es inherentemente interactivo, pero no anunciará un rol. Se marcará el elemento como una violación de accesibilidad.
Ejemplo Fallido ❌
La tarjeta es clicable, pero la foto de perfil dentro de ella es enfocable por separado.
TalkBack no anuncia el rol de la tarjeta ni el aviso "Toque dos veces para activar", y en cambio se enfoca y anuncia el elemento interno.
Los usuarios no saben que la tarjeta es interactiva y el elemento con foco no es clicable.
Ejemplo Con Éxito ✅
El elemento interno ya no es enfocable por separado.
TalkBack se enfoca en la tarjeta misma y anuncia su contenido, rol y "Toque dos veces para activar."
Los usuarios entienden que la tarjeta es interactiva y pueden activarla.
Resumen
- Esta regla tiene un impacto crítico para los usuarios de TalkBack y Voice Access
- Cuando un elemento hijo roba el enfoque de un padre clicable, se pierde el rol interactivo
- TalkBack no anunciará "Toque dos veces para activar" si el elemento enfocado no es clicable por sí mismo
- La solución siempre es eliminar la capacidad de enfoque del elemento anidado, no agregarle un rol
- Las vistas de contenedor que no tienen acción no deben dejarse clicables, esto evita falsos positivos
Impacto para los Usuarios
Cuando la tecnología de asistencia no anuncia un rol, los usuarios ciegos o con baja visión que dependen de TalkBack no sabrán que pueden activar una acción. Por ejemplo, TalkBack se enfoca en un elemento interno y anuncia solo su texto (por ejemplo, "Tema"). No anuncia que es un botón o que el usuario debe tocar dos veces para activar. Los usuarios se quedan sin el contexto necesario para interactuar con la pantalla.
Confirmar el Problema de Elemento Enfocable Anidado
- Activa TalkBack
- Enfócate en el elemento y cada uno de sus descendientes
- Ocurrirá una de las siguientes situaciones:
- Inaccesible: TalkBack lee el texto pero no anuncia un rol ni la capacidad de interactuar
- Accesible: TalkBack lee todo el texto y también anuncia un rol y/o cómo interactuar con el elemento
Corregir Problemas
Elimina la capacidad de enfoque de los elementos anidados para que el padre clicable pueda obtener el enfoque y anunciar su rol. No agregues propiedades de enfoque a los descendientes no interactivos de una vista clicable.
Para evitar un hallazgo falso positivo, asegúrate de que los elementos contenedores que no hacen nada cuando se tocan no sean clicables. Nuestras herramientas no pueden determinar si un elemento clicable tiene una acción programada asociada, por lo que debemos asumir que lo tiene para señalar un comportamiento potencialmente inaccesible.
Examina los elementos contenedores circundantes, como Frames, Card Views o Drawers, para asegurarte de que cualquier elemento sin una acción asociada no se configure como clicable.
XML
En el siguiente ejemplo, el MaterialCardView es clicable, pero si uno de los hijos - LinearLayout o TextView - tiene focusable="true", TalkBack se enfocará en eso en lugar de la tarjeta. En su estado predeterminado la propiedad focusable de ambos LinearLayout y TextView es falsa. Asegúrate de que no esté configurada como verdadera, para que la tarjeta pueda obtener el enfoque y anunciar su papel interactivo.
<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>Composición
En este ejemplo, el Card es clicable, pero si uno de los hijos - Row o Text - tiene un atributo .focusable(), TalkBack se enfocará en él en su lugar. Asegúrate de que el Row o Text no tenga un atributo .focusable(), para que el Card pueda obtener el enfoque, anunciar su contenido de texto y transmitir su papel interactivo (por ejemplo, "Toque dos veces para activar").
Card(
modifier = Modifier
.clickable {
openContact(context)
}
) {
Row(
modifier = Modifier
.padding(10.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.CenterHorizontally)
) {
Text("Sarah Anderson")
}
}.NET MAUI
En el siguiente ejemplo, la tarjeta de contacto Grid tiene un TapGestureRecognizer para abrir el contacto. Si un elemento hijo dentro del Grid es enfocable de manera independiente, TalkBack se enfocará en él en lugar de la tarjeta. Asegúrate de que ningún elemento hijo tenga AutomationProperties.IsInAccessibleTree="true" configurado explícitamente, para que el Grid retenga el enfoque y pueda anunciar "Toque dos veces para activar".
<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
En este ejemplo, la tarjeta de contacto es un TouchableOpacity con propiedades de accesibilidad configuradas directamente en él. Las propiedades accessible={true} y accessibilityRole="button" aseguran que TalkBack anuncie la tarjeta como un elemento interactivo. Las vistas hijo dentro de ella no deben tener accessible={true} configurado de manera independiente, lo que causaría que roben el enfoque de la tarjeta.
<TouchableOpacity
accessible={true}
accessibilityRole="button"
style={styles.contactCard}
onPress={() => openContact("sarah-anderson")}
>
<Text>Sarah Anderson</Text>
<Text>sarah@example.com</Text>
</TouchableOpacity>Flutter
En este ejemplo, la tarjeta de contacto es un Card con un InkWell que maneja el toque. Si un widget hijo dentro del Card tiene su propio Semantics con button: true o onTap configurado, TalkBack se enfocará en él en lugar de la tarjeta. Mantén el manejador de toque en el InkWell y asegúrate de que ningún widget descendiente reclame enfoque de manera independiente.
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"),
],
),
),
),
)¿Puedo Ignorar Esta Regla?
Elemento Enfocable Anidado tiene un impacto crítico para los usuarios, y recomendamos encarecidamente corregir este problema. Cuando el enfoque recae en un elemento no interactivo dentro de un padre clicable, los usuarios de TalkBack no tienen manera de saber que el elemento puede ser activado. Ignorar esta regla significa que esos usuarios no podrán interactuar efectivamente con el elemento afectado. Aprende más sobre ignorando reglas.
Recursos
Páginas de Curso de Deque University
Nota: El acceso completo a los recursos de Deque University requiere una suscripción.
Otros recursos
- Directrices de Accesibilidad para el Contenido Web (WCAG) 2.1, Recomendación del W3C
- Documentos de comprensión de WCAG 2.1
