VoiceOver no iOS: Resolvendo problemas comuns

Quando você tenta adaptar o aplicativo para cegos, geralmente algo sai errado: ou a ordem será perdida e o foco não chegará lá. Por outro lado, existe o UX, que é fácil de perder, porque você não conhece os possíveis problemas. Neste artigo, lidaremos com problemas típicos e suas soluções.



A adaptação do aplicativo iOS é um grande tópico, tudo não se encaixava em um artigo, então eu os libero em uma série.

  1. Controle por voz e VoiceOver: como adaptar o aplicativo para cegos ou imóveis .
  2. VoiceOver no iOS: cada controle se comporta de maneira diferente.
  3. VoiceOver no iOS: solução de problemas comuns.
  4. A diferença entre a implementação dos testes VoiceOver, Voice Control e UI. (Em progresso)

Na primeira parte, lidamos com a adaptação de aplicativos para cegos usando o VoiceOver: controles assinados, agrupados, navegação fixa. Na segunda parte, fomos além e examinamos os “recursos” que podem ser dados aos controles, a fim de melhorar seu trabalho para pessoas cegas e, geralmente, melhorar a usabilidade do aplicativo.

Hoje, continuaremos trabalhando na adaptação da tela da pizza: alteraremos a ordem de rastreamento, resumiremos as informações de compra, corrigiremos a janela modal e melhoraremos o indicador de carregamento.

Controla o reordenamento


Se você não definir a ordem correta de aprovação dos controles no VoiceOver, provavelmente ele ignorará e lerá os elementos na ordem errada, como você gostaria. Por exemplo, isso aconteceu com os botões "fechar" e "na cesta".

A tela irá rolar e os botões estão acima UIScrollView. Acontece que o VoiceOver primeiro tenta ignorar todos os elementos internos UIScrollViewe só então encontra os botões superiores. Para o usuário, esse comportamento do VoiceOver estará errado: os botões estão na parte superior, portanto a iteração e a pontuação devem começar com eles.

Para começar, vamos primeiro descobrir como o VoiceOver determina a ordem dos controles. Ele faz assim: pega elementos de uma propriedade accessibilityElements. Por padrão, todos vieweles estão lá isAccessibilityElement = true.

Agora podemos colocar os botões no início substituindo accessibilityElements:

override var accessibilityElements: [Any]? {
    get {
        var elements = [Any]()
            
        elements.append(contentsOf: [closeButton, cartButton])
        elements.append(contentsOf: contentScrollView.accessibilityElements)
            
        return elements
    }
    set { }
}

Agrupar através de shouldGroupAccessibilityChildren


Normalmente, o VoiceOver tenta ler os elementos em uma ordem natural - da esquerda para a direita, de cima para baixo:



Se você tiver agrupado os controles, precisará do VoiceOver para ir para o elemento mais próximo do agrupamento, e não na ordem de leitura. Defina .shouldGroupAccessibilityChildren = truee o pedido começará a levar em consideração a proximidade dos elementos. A propriedade deve ser configurada como pai viewde todos os elementos.



Aponte o primeiro item para focar


Outro problema de ordem de leitura é quando o VoiceOver abre a tela pela primeira vez e seleciona o elemento superior esquerdo. Na maioria das vezes, esse é o botão Voltar. Por um lado, isso permite que você retorne rapidamente à tela anterior se cometer um erro. Por outro lado, é assim que perdemos a compreensão de em que tela estamos. Você pode corrigir a situação se definir manualmente o foco para o controle desejado.

O que a Apple faz?
É estranho que UINavigationControllercoloque o foco no botão "Voltar", eu poderia colocá-lo no título da tela que se abre. Do lado da conveniência, parece-me correto focar no título ou no primeiro controle, para fornecer mais informações sobre a nova tela. Você pode voltar com um gesto de limpeza .

Você pode reorganizar o foco usando a função de alerta UIAccessibility.post(notification: …). São necessários dois parâmetros:

  • Uma das espécies UIAccessibility.Notification.
  • O objeto ao qual o alerta deve ser aplicado. Na maioria das vezes, essa é uma linha com texto ou objeto que deve ser selecionado após a notificação.

Você pode colocar o foco no cabeçalho em viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
        
    UIAccessibility.post(notification: .screenChanged,
                         argument: titleLabel);
}

Você pode transferir o objeto no qual deseja colocar o foco ou o texto a ser pronunciado.

Tipos de alertas para objetos


  • .screenChanged — , . - .
  • .layoutChanged — . , , «» .
  • .announcement — . . , . , .

    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
    		UIAccessibility.post(notification: .announcement,
                             argument: text)
    }
  • .pageScrolled.UIScrollView « 3 5», . , , .
  • .pauseAssistiveTechnology .resumeAssistiveTechnology —  VoiceOver.

Mostrar janelas modais nativamente


Ao trabalhar com o VoiceOver, você pode (e irá) gravar todos os batentes permitidos no desenvolvimento. Por exemplo, criamos um feed de mensagens e, para que as mensagens começassem de baixo, decidimos inverter UITableViewe depois inverter todas as células. Visualmente, está tudo bem, mas a lista rolará de cabeça para baixo com três dedos no VoiceOver.

Também enfrentamos um problema em que não podíamos alterar os ingredientes de nenhuma maneira, porque não era possível colocar o foco na janela. Aconteceu porque mostramos a visualização, e não UIViewControllercom um UIPresentationController.VoiceOver especial .firstResponder, e o nosso viewnão.



Se não houver tempo para reescrever, você poderá viewdefinir a propriedade para accessibilityViewIsModal. O VoiceOver se concentrará apenas nisso view.

override var accessibilityViewIsModal: Bool {
    get { return true }
    set {}
}

Para ser honesto, nunca funcionou para mim, e nós UIPresentationController.

Alinhar quadros invisíveis


A ordem de leitura é contada por quadros, às vezes fornece resultados inesperados. Por exemplo, ampliamos o quadro do botão "i" para facilitar o clique. Mas acabou sendo mais alto do que o quadro do nome da pizza, então o botão "i" acabou sendo o primeiro elemento de foco. Mesmo sendo pequeno, está à direita e geralmente não é tão importante.



Você pode alterar a ordem de leitura accessibilityElements, mas mostrarei uma maneira diferente. O VoiceOver usa a propriedade accessibilityFrame; por padrão, ela corresponde ao quadro usual. Existem várias soluções:

  1. Substitua a subclasse de controle e retorne um valor reduzido.
  2. Coloque o quadro correto do lado de fora.
  3. Basta ajustar o quadro para que fique alinhado com a inscrição.

Mas é importante que esse quadro esteja nas coordenadas da tela. Para uma conversão simples, existe uma função UIAccessibility.convertToScreenCoordinates.

Também pode ser usado para combinar controles. Por exemplo, você precisa combinar o switcher e sua assinatura, para que o elemento fique maior, seja mais fácil clicar nele, a duplicação desnecessária desaparecerá.

override func layoutSubviews() {
        super.layoutSubviews()
        repeatSwitch.accessibilityLabel = repeatLabel.text
        repeatSwitch.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(
                repeatSwitch.frame.union(repeatLabel.frame).insetBy(dx: -12, dy: -12),
                in: repeatSwitch.superview!)
}

Também ampliei o foco usando .inset, é mais conveniente pressionar.



Usando o quadro, AccessibilityContainervocê pode disponibilizar gráficos e tabelas.

Resuma a ação principal


Isso é mais sobre o UX, mas vou lhe dizer de qualquer maneira. Uma pessoa com visão normal lê com facilidade todas as configurações da tela, mas, para essa pessoa cega, é necessário classificar manualmente todos os controles. Você pode facilitar o processo e resumir todas as alterações no botão Comprar.

Por exemplo, para obter o "botão Comprar. Adicione o bacon, remova os jalapenos. Preço 434₽ », você não precisa escrever nada incomum no código, basta coletar a linha com adição / remoção:

accessibilityTraits = .button
accessibilityLabel = ""
accessibilityValue = " ,  .  434₽" 

E não se esqueça de assinar o indicador de download


Se, após adicionar um produto ao carrinho, você bloquear brevemente a interface e baixar algo, não se esqueça de disponibilizar o indicador de download:

  1. Use o alerta para focar no indicador.
  2. Dê um nome ao foco. Por exemplo, carregando.
  3. Coloque isso accessibilityViewIsModal.
  4. Avise-me quando o download terminar.

Se, após o carregamento, você exibir uma nova tela, o VoiceOver mudará o foco, tornando claro que o download foi encerrado. Em casos mais complicados, você pode dizer isso explicitamente ou até mesmo adicionar vibração .

O que a Apple faz?
Curiosamente, o Safari trabalha com isso no iOS 13: durante o carregamento da página, ele clica a cada segundo e, quando uma página é carregada, faz * woop-dumb *. Infelizmente, do lado da API, isso ainda não está disponível, estamos aguardando o iOS 14.



Para adaptar a tela, usamos diferentes abordagens: alteramos a ordem dos botões, indicamos o primeiro elemento de foco, corrigimos a janela modal, resumimos as configurações no botão principal e trabalhamos na conveniência do aplicativo. Esse conhecimento é suficiente para adaptar quase qualquer aplicativo. Continue.

Na próxima vez, falarei sobre a diferença entre a implementação dos testes VoiceOver, Voice Control e UI.
Para não perder o próximo artigo, assine o meu canal Dodo Pizza Mobile .

All Articles