Focus Order — qué es, principios y cómo configurarlo en aplicaciones móviles

Autor: IT Sectr Publicado: 2026-05-16 Tiempo de lectura: 9 min

Focus Order es la secuencia en la que los elementos de la interfaz reciben el foco al navegar con un teclado, Switch Control, VoiceOver o TalkBack. En aplicaciones móviles, el orden de foco determina cómo el usuario se desplaza entre los controles mediante gestos o botones. Según W3C WCAG 2.2, Success Criterion 2.4.3, 2023, el foco debe seguir un orden lógico que preserve el significado del contenido. La violación de este principio es una de las causas comunes de fracaso en una auditoría de accesibilidad.

Puntos clave

  • Focus Order — la secuencia de recorrido de los elementos interactivos al navegar con un teclado o lector de pantalla
  • El foco debe seguir el orden visual (de izquierda a derecha, de arriba abajo) y preservar la lógica del contenido
  • En iOS, el orden se regula mediante shouldGroupAccessibilityElement y el array accessibilityElements
  • En Android, los atributos nextFocusDown, nextFocusUp, nextFocusLeft, nextFocusRight definen los vecinos de foco
  • Las pantallas personalizadas (mapas, lienzos, juegos) requieren gestión programática del foco mediante UIAccessibilityPostNotification

Qué es Focus Order en accesibilidad

Focus Order es la secuencia en la que el usuario se desplaza entre los elementos interactivos utilizando métodos de entrada alternativos: teclado (Tab), Switch Control (paso a paso), VoiceOver (deslizar derecha/izquierda) o TalkBack. A diferencia de un ratón o pantalla táctil, donde el usuario selecciona un elemento directamente, la navegación por foco es lineal — cada paso mueve el foco al siguiente elemento.

Según Apple HIG, 2024, VoiceOver utiliza el orden de los elementos en el árbol de accesibilidad, que se construye en función de la ubicación visual: esquina superior izquierda → esquina inferior derecha. Si la pantalla tiene un diseño complejo (columnas, Grid, ZStack), el árbol puede no coincidir con el orden visual.

Principio de WCAG 2.4.3: “Si una página web puede navegarse secuencialmente por secciones y el orden de foco afecta el significado, entonces el foco debe seguir un orden que preserve el significado y la operatividad”. Excepción: contenido dinámico donde el foco puede saltar para llamar la atención (alertas, ventanas modales).

Por qué Focus Order es crítico para la accesibilidad

Un usuario de Switch Control (personas con discapacidades motoras) se desplaza por los elementos automáticamente — ciclo tras ciclo. Si el orden está roto, el usuario tarda 3 veces más en completar el formulario. Según Deque University, 2024, un Focus Order correcto reduce el tiempo de completado del formulario en un 60% para usuarios de tecnologías de asistencia.

Focus Order y ventanas modales

Atención especial — ventanas modales. Después de abrir una modal, el foco debe moverse inmediatamente al primer elemento interactivo dentro de la modal (normalmente un botón “Cerrar” o “Confirmar”). Al cerrar — volver al elemento que activó la modal. Este es un requisito de WCAG 2.4.3 y también un error común.

iOS: gestión del orden de foco

En iOS, VoiceOver construye automáticamente el orden basándose en la geometría: los elementos se ordenan por Y, luego por X. Para pantallas con estructura compleja, este orden puede ser incorrecto — el desarrollador debe intervenir.

Herramientas principales:

  • shouldGroupAccessibilityElement — agrupa elementos hijos en un bloque lógico
  • accessibilityElements — array que define el orden personalizado de los elementos hijos
  • UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, element) — movimiento programático del foco

Ejemplo de configuración de orden personalizado para una tarjeta de producto:

swift
class ProductCardView: UIView {
    let titleLabel = UILabel()
    let priceLabel = UILabel()
    let buyButton = UIButton()

    override var accessibilityElements: [Any]? {
        get {
            return [titleLabel!, priceLabel!, buyButton!]
        }
        set {}
    }
}

Para el movimiento programático del foco después de una acción:

swift
UIAccessibility.post(
    notification: .layoutChanged,
    argument: newlyAddedItem
)

shouldGroupAccessibilityElement en la práctica

La propiedad shouldGroupAccessibilityElement es útil para tarjetas en colecciones. Si se establece en true en la tarjeta padre, VoiceOver percibe toda la tarjeta como un solo elemento. El usuario puede tocar dos veces para activar la tarjeta completa, o configurar el rotor para la navegación interna. Recomendado para UICollectionViewCell y UITableViewCell.

Android: atributos de dirección de foco

En Android, TalkBack también utiliza el orden geométrico, pero se da prioridad a los atributos explícitos nextFocus*. Estos atributos se establecen en XML o programáticamente:

AtributoPropósitoEjemplo
nextFocusDownElemento al navegar hacia abajo@+id/field_email
nextFocusUpElemento al navegar hacia arriba@+id/field_name
nextFocusLeftElemento a la izquierda@+id/btn_back
nextFocusRightElemento a la derecha@+id/btn_next

Ejemplo para un formulario de registro:

xml
<EditText
    android:id="@+id/field_email"
    android:nextFocusDown="@+id/field_password" />

<EditText
    android:id="@+id/field_password"
    android:nextFocusDown="@+id/btn_submit" />

Para RecyclerView, el orden de foco es dinámico — lo determina el adaptador. Si las celdas tienen una estructura compleja, establezca descendantFocusability = “beforeDescendants” y defina el orden en el nodo del elemento de la lista. Para Jetpack Compose, el orden de foco se establece mediante Modifier.focusOrder() y FocusOrder. Prioridad: previous (hijo), next (siguiente), clave personalizada.

TouchDelegate, área de impacto y área de foco

Si un elemento es demasiado pequeño para el foco (menor de 44pt), aumente el área de impacto mediante TouchDelegate en iOS o minWidth/minHeight en Android. Según Google Material Design, 2024, el área táctil mínima es de 48×48dp. VoiceOver y TalkBack se centran en el cuadro delimitador del elemento. Los elementos de menos de 30pt pueden ser inaccesibles para el foco gestual — el usuario físicamente no puede tocarlos.

Violaciones comunes de WCAG 2.4.3

Foco saltarín — cuando después de una acción (por ejemplo, eliminar un elemento) el foco se mueve al inicio de la lista o al botón “Volver” del sistema. El usuario de VoiceOver pierde el contexto. Solución: mover programáticamente el foco al elemento más cercano al eliminado.

Foco invisible — un elemento recibe foco pero no hay indicador visual (los usuarios de teclado no ven dónde están). En iOS, verifique UIAccessibility.isVoiceOverRunning para indicadores personalizados. Según Deque University, 2024, el foco invisible es la segunda causa más común de fracaso en una auditoría de accesibilidad.

Modales — el foco permanece en el contenido de fondo después de abrir una modal. En iOS, la vista modal captura automáticamente el foco si se establece modalPresentationStyle = .pageSheet. En Android, use setFocusable(true) en el contenedor del diálogo.

Trampa de foco

El problema inverso: el foco se queda atascado dentro de una modal y no puede salir (excepto cerrándola). Esto es aceptable solo para ventanas modales — el usuario debe cerrar la ventana intencionadamente. Para pantallas normales, la trampa de foco es un error crítico. Solución: asegúrese de que el último elemento de la modal (el botón “Cerrar”) devuelva el foco.

Pantallas personalizadas y foco programático

Para pantallas personalizadas (mapas, lienzos, juegos) el orden geométrico automático no es aplicable. El desarrollador debe construir el árbol de accesibilidad manualmente. En iOS, para esto se sobrescribe el método UIAccessibilityContainer.

Ejemplo para un lienzo personalizado:

swift
class CanvasView: UIView {
    var shapes: [ShapeView] = []

    override var accessibilityElements: [Any]? {
        get {
            // Ordenar formas por Z-index, no por geometría
            return shapes.sorted { $0.zIndex < $1.zIndex }
        }
        set {}
    }
}

En Android, para una View personalizada, sobrescriba onInitializeAccessibilityNodeInfo:

kotlin
override fun onInitializeAccessibilityNodeInfo(
    info: AccessibilityNodeInfo
) {
    super.onInitializeAccessibilityNodeInfo(info)
    info.addChild(firstElement)
    info.addChild(secondElement)
    info.isFocusable = true
}

Para listas dinámicas (chat, feed de noticias), después de añadir un elemento, mueva el foco al primer elemento nuevo. En iOS: UIAccessibility.post(notification: .layoutChanged, argument: newMessage). En Android: sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED).

AccessibilityFrame y geometría de foco

iOS determina automáticamente el área de foco basándose en el marco del elemento. Si un elemento tiene una transformación (transform, rotation), VoiceOver puede enfocar el área incorrecta. Establezca explícitamente accessibilityFrame en coordenadas de pantalla: element.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(element.bounds, in: element). Esto garantiza que VoiceOver resalte el área correcta.

UIKit Dynamics y accesibilidad

Para pantallas animadas (UIKit Dynamics, Lottie, SpriteKit), el foco programático es especialmente importante. VoiceOver no puede construir un árbol de accesibilidad para elementos que se mueven dinámicamente. Establezca isAccessibilityElement = false en los contenedores de animación y true solo en los elementos interactivos del interior.

Pruebas del orden de foco

Pruebas manuales: active VoiceOver (iOS) o TalkBack (Android), deslice hacia la derecha por toda la secuencia. El foco debe seguir el orden visual — de izquierda a derecha, de arriba abajo. Cada elemento interactivo debe recibir el foco exactamente una vez.

Pruebas automatizadas son difíciles pero posibles:

swift
func testKeyboardFocusOrder() {
    let app = XCUIApplication()
    app.launch()
    app.textFields["Email"].tap()
    // Tab — solo con teclado físico
}

Para Android, use el Accessibility Testing Framework:

kotlin
@Test
fun testFocusOrder() {
    onView(withId(R.id.fieldEmail))
        .check(matches(isFocusable()))
    onView(withId(R.id.fieldEmail))
        .perform(focus())
    onView(withId(R.id.fieldPassword))
        .check(matches(isFocused()))
}

El método más fiable es una prueba de escenario de UI: rellene el formulario paso a paso (Email → Contraseña → Enviar), comprobando que cada paso se completa correctamente. Si el orden de foco está roto, el escenario fallará al intentar interactuar con un elemento fuera de foco.

Xcode Accessibility Inspector para depuración

La herramienta Accessibility Inspector en Xcode muestra el árbol de accesibilidad completo. Puede recorrer los elementos en el orden de VoiceOver y ver la ruta de foco exacta. Use la pestaña “Audit” para la detección automática de violaciones de Focus Order.

Preguntas frecuentes

Qué es WCAG 2.4.3 y cuáles son los requisitos de foco?

WCAG 2.4.3 (Focus Order) es un criterio de éxito de nivel A. Requiere que el orden de foco preserve el significado del contenido durante la navegación secuencial. La violación se considera crítica y bloquea la certificación.

Cómo establecer el orden de foco para elementos ocultos tras animaciones?

Los elementos ocultos deben tener isAccessibilityElement = false en iOS o visibility = gone/invisible en Android. Cuando aparezcan, mueva programáticamente el foco mediante UIAccessibility.post(notification: .layoutChanged).

En qué se diferencia el foco en iOS de Android?

iOS gestiona mediante accessibilityElements y shouldGroupAccessibilityElement, Android mediante atributos nextFocus* y AccessibilityNodeInfo. El principio es el mismo: orden geométrico por defecto con posibilidad de sobrescribirlo.

Qué hacer si RecyclerView tiene un orden incorrecto?

Establezca descendantFocusability = “beforeDescendants” en el elemento raíz y configure el orden en el adaptador mediante onInitializeAccessibilityNodeInfo para cada celda.

Cómo probar el foco sin VoiceOver?

Conecte un teclado físico mediante Bluetooth o USB. En iOS pulse Tab para mover el foco. En Android active TalkBack y use las teclas Tab y las flechas.

Resumen

  • Focus Order — la secuencia de recorrido de los elementos al navegar con un teclado o lector de pantalla; basado en WCAG 2.4.3
  • El foco debe seguir el orden visual (de izquierda a derecha, de arriba abajo) — automáticamente en VoiceOver y TalkBack
  • En iOS, el orden se regula mediante accessibilityElements y shouldGroupAccessibilityElement
  • En Android se usan los atributos nextFocusDown, nextFocusUp, nextFocusLeft, nextFocusRight
  • Las pantallas personalizadas (mapas, lienzos) requieren gestión programática del foco mediante UIAccessibilityPostNotification
  • La violación del orden es un error crítico en WCAG 2.4.3; los usuarios pierden el contexto y no pueden completar el escenario
  • Pruebe el foco mediante gestos de VoiceOver/TalkBack, teclado físico y escenarios automatizados

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también