VoiceOver en iOS: cada control se comporta de manera diferente

Hola Habr! Recientemente, hablé sobre la adaptación de aplicaciones para personas ciegas e inmóviles. ¡Y no lo terminé!

Hoy les diré cómo cambiar el comportamiento de los controles con la ayuda accessibilityTraitsy hacer que la vida de los ciegos sea un poco más conveniente. Conocer el trabajo de estos rasgos es importante para no escribir sus muletas.



La adaptación de la aplicación iOS es un gran tema, no todo encaja en un artículo, por lo que los lanzo en una serie.

  1. Control de voz y VoiceOver: cómo adaptar la aplicación para ciegos o quietos .
  2. VoiceOver en iOS: cada control se comporta de manera diferente.
  3. VoiceOver en iOS: Solución de problemas comunes.
  4. La diferencia entre la implementación de VoiceOver, Voice Control y las pruebas de IU. (En progreso)

En la primera parte, comenzamos a tratar con la adaptación de aplicaciones para ciegos usando VoiceOver: controles firmados, agrupados, navegación fija. En este artículo, iremos más allá y consideraremos las "características" que se pueden dar a los controles para mejorar su trabajo para las personas ciegas y, en general, mejorar la usabilidad de la aplicación.

Características de control - Colección de rasgos


VoiceOver tiene un conjunto estándar de "características" UITraitCollectionque puede aplicar a los controles. Es importante conocerlos de antemano para no encontrar sus propias soluciones. Los dividí en tres tipos:

  1. Tipo de control.
  2. El estado de control.
  3. Propiedades especiales de los controles.

Enseguida mostraré en un ejemplo de una pantalla con una tarjeta de pizza:



Tipo de control


VoiceOver conoce algunos tipos de elementos básicos. Algunos de ellos ya están configurados en su proyecto, pero les contaré de todos modos.

Los tipos de controles se utilizan para la navegación: puede navegar rápidamente a través de ellos utilizando el rotor .

  • .staticText- para inscripciones que no cambian. El texto es fácil de leer.
  • .header- encabezado: Agregar a la pizza, encabezado.
  • .button- botón La forma principal de firmar controles activos: Cambiar la composición, botón.
  • .image - imagen.
  • .link- enlace. Un invitado raro en aplicaciones, frecuente en sitios.
  • .searchField - Buscar.

Veamos un ejemplo:


  1. Indica el título. .staticTextconfigurado automáticamente para todas las etiquetas, pero .headerpara el título debe ponerlo manualmente. Cuando esto necesita y .headery .staticText.
  2. Marque el lugar debajo de la imagen. La última vez que ocultamos todas las imágenes pequeñas de VoiceOver, no perdimos contenido informativo. Esta vez la imagen es grande, no es tan fácil de ocultar: el lugar se vaciará, esto es extraño. Marcamos la imagen cuando la .imagefirmamos .accessibilityLabel = " ".

Por supuesto, los botones de cierre y la canasta deben estar firmados, esto fue en el último artículo.

Estado de control


El control puede tener tres estados: normal, seleccionado y deshabilitado. Es interesante que se pronuncian en diferentes momentos y se pueden seleccionar al mismo tiempo:



  • .selected- agrega "seleccionado" delante del nombre del control. Apto para todos los interruptores y casillas de verificación.
  • .notEnabled- agrega "no disponible". Esta configuración no es visible Interface Buildery solo se controla mediante programación.

Un ejemplo de agregar coberturas a la pizza: al


usar estados, puede explicarle al usuario que se ha agregado la cobertura. Es conveniente arreglarlo dentro de la celda. accessibilityTraitsesta OptionSetes la razón por la cual se le pueden aplicar métodos de inserción .formUniony eliminación .formIntersection:

class ToppingCell: UICollectionViewCell {
    override var isSelected: Bool {
        didSet {
            if isSelected {
                accessibilityTraits.formUnion(.selected)
            } else {
                accessibilityTraits.formIntersection(.selected)
            }
        }
    }
    ...
}

Propiedades especiales de los controles.


Hay algunas propiedades más inusuales. En nuestro caso, no se ajustan a la pantalla de la pizza, pero les contaré sobre ellos de todos modos, porque hay poca información sobre ellos. Quizás esto te ahorre tiempo.

  • .summaryElement — , . , , . , .
  • .updatesFrequently —  . .
  • .causesPageTurn —  . accessibilityScroll(.next) , . .firstResponder.
  • .startsMediaSession —  VoiceOver , . , . , VoiceOver .
  • .playsSound —  , ( , ).
  • .allowsDirectInteraction- para dibujar y manejar gestos. El control procesa inmediatamente el toque como si VoiceOver estuviera apagado.
  • .keyboardKey- el control comienza a reaccionar como un botón en el teclado. VoiceOver tiene varios modos de ingreso de texto para tales casos:

    - standart typingcomo un simple botón en VoiceOver: primero enfóquese en la letra y luego toque dos veces en cualquier lugar para escribirla. Puede escribir más rápido con ambas manos: maneje el teclado con un dedo (las letras tendrán voz) y toque con el otro dedo para confirmar la selección de teclas.
    - touch typing- Marcación rápida con un solo brazo: deslice el dedo por el teclado hasta los botones de voz. Suelta tu dedo para escribir la carta.
    - direct touch typing- como un conjunto normal, como si VoiceOver estuviera desactivado.

Video sobre diferentes métodos de entrada:


Simplemente marque la casilla IB para agregar comportamiento. Con el rasgo ajustable simplemente no será tan fácil, por separado.

Configurando el poderoso rasgo .adjustable


Y el último rasgo, especialmente importante, .adjustablees un elemento que puede regularse: así es cómo UISteppery cómo funciona UISlider. Deslice este control hacia arriba o hacia abajo para cambiar el valor (no olvide que deslizar hacia la izquierda / derecha cambiará el foco al elemento vecino). Si el control tiene un UIPanGestureRecognizer, puede tocar dos veces y mantener presionado el segundo toque, por lo que el gesto funcionará y podrá controlarlo directamente, como si VoiceOver estuviera apagado.

Ejemplos de aplicación para .adjustable:

Interruptor de prueba. La configuración de la prueba consta de cinco botones: tres para elegir el tamaño de la pizza y dos para el tipo de prueba. Deben agruparse y firmarse para que en lugar de cinco queden dos: “Tamaño, promedio. Elemento de ajuste " y“Masa, tradicional. Elemento de ajuste ".



Necesidad de hacer en 4 pasos:

  1. Haga el contenedor con botones disponibles.
  2. Pon un rasgo .adjustable.
  3. Implementar métodos de aumento y disminución.
  4. Devuelve el nuevo valor para .accessibilityValue.

override public func awakeFromNib() {
        super.awakeFromNib()
        
        isAccessibilityElement = true // 1
        accessibilityTraits = .adjustable // 2
    }


extension SegmentedControl {
    override public func accessibilityIncrement() { // 3
        controller.selectNext(increment: +1)
    }
    
    override public func accessibilityDecrement() { // 3
        controller.selectNext(increment: -1)
    }
    
    public override var accessibilityValue: String? { // 4
        get {
            return selectedSegment?.accessibilityValue
        } set { }
    }
}

Ahora, después de activar el deslizamiento hacia arriba accessibilityIncrement(), aumentará el contador interno y VoiceOver leerá el nuevo valor del accessibilityValue.

Conteo de la cantidad total en el mundo. En este bloque vemos cuatro controles: botón menos, cantidad, botón más y precio. Puede combinarlos en uno viewy convertirlos en un control: “Cantidad, 1, 575 rublos. Elemento de ajuste ". Después de un deslizamiento vertical, la cantidad cambiará, y luego se pronunciará un nuevo valor junto con el precio.



Horizontal UICollectionView. Resultó que es .adjustableconveniente aplicar para horizontal UICollectionView. Por ejemplo, elija compartir en el menú o un automóvil en un taxi.



Conclusión


Esta vez distinguimos los rasgos: sus tipos, estados y comportamiento. Este es un conjunto estándar para tareas comunes . Para controles complejos, puede usar .adjustable.

La próxima vez, veamos una solución a problemas comunes : omitir el orden, ventanas modales, indicadores de carga.

Para no perderse el siguiente artículo, suscríbase a mi canal Dodo Pizza Mobile .

Y ahora tenemos una vacante en la dirección móvil. Así que solo lo dejo aquí: Senior iOS Developer (Nizhny Novgorod).


All Articles