Accessibility Trait: essência, tipos e como funcionam no desenvolvimento

Autor: IT Sectr Publicado: 2026-05-16 Tempo de leitura: 9 min

Accessibility Trait é uma propriedade de elemento iOS que determina sua função e comportamento para o VoiceOver. O trait informa ao screen reader como o elemento deve ser anunciado e quais gestos estão disponíveis: se é um botão, cabeçalho, link ou campo de busca. De acordo com Apple UIAccessibilityTraits, 2024, o sistema suporta mais de 15 constantes que podem ser combinadas usando uma máscara de bits. Um trait escolhido corretamente economiza até 50% do tempo de navegação para usuários do VoiceOver.

Pontos-Chave

  • Accessibility Trait — a função de um elemento iOS para o VoiceOver; definida através das constantes UIAccessibilityTraits
  • Traits podem ser combinados usando o operador | para criar funções complexas (botão + selecionado)
  • Cada elemento pode ter vários traits simultaneamente, mas não mais que 3-4 para evitar confusão
  • Um trait incorreto (por exemplo, StaticText para um botão) quebra o cenário de interação: o usuário não sabe se um gesto está disponível
  • No Android, o equivalente são os atributos role e className no AccessibilityNodeInfo

O que é Accessibility Trait

Accessibility Trait é uma flag definida em um elemento UIView para indicar sua função semântica ao VoiceOver. O trait é um dos três componentes da tríade de acessibilidade da Apple: Label (nome), Hint (descrição), Trait (função). O iOS usa a máscara de bits UIAccessibilityTraits (UInt64), onde cada bit corresponde a uma função específica. O VoiceOver lê a função após Label e Hint: “Botão Enviar. Abrirá um formulário” — “Botão” é adicionado graças ao trait UIAccessibilityTraitButton.

Por padrão, UIButton recebe UIAccessibilityTraitButton, UILabel recebe UIAccessibilityTraitStaticText, UIImageView recebe UIAccessibilityTraitImage. Ao usar controles personalizados, o desenvolvedor deve definir o trait manualmente. Apple Human Interface Guidelines, 2024, chamam isso de “um dos passos mais críticos para garantir a acessibilidade”.

Sem o trait correto, o usuário não sabe qual gesto aplicar: toque simples (ativação de botão), toque duplo (zoom) ou gesto de deslizar (alternar). O trait determina quais gestos do VoiceOver são ativados no elemento.

Implementação técnica de UIAccessibilityTraits

UIAccessibilityTraits é um typealias UInt64. Cada trait é uma constante com exatamente um bit definido. Por exemplo, UIAccessibilityTraitButton = 0x0000000000000001, UIAccessibilityTraitLink = 0x0000000000000002, UIAccessibilityTraitHeader = 0x0000000000000008. Combinações são alcançadas com OR bit a bit: 0x0001 | 0x0008 = 0x0009. O VoiceOver analisa a máscara e determina o comportamento.

Principais tipos de traits iOS

O iOS fornece mais de 15 constantes de traits. Vamos ver os principais usados em 90% dos cenários:

TraitConstanteComportamento do VoiceOver
ButtonUIAccessibilityTraitButtonAtivação por toque duplo
HeaderUIAccessibilityTraitHeaderNavegação rápida por cabeçalhos
LinkUIAccessibilityTraitLinkAtivação como link
StaticTextUIAccessibilityTraitStaticTextSomente leitura, sem ativação
SearchFieldUIAccessibilityTraitSearchFieldCampo de busca com comportamento especial
ImageUIAccessibilityTraitImageImagem, sem gesto de ativação
SelectedUIAccessibilityTraitSelectedEstado “selecionado”
PlaysSoundUIAccessibilityTraitPlaysSoundReproduz som ao ativar
KeyboardKeyUIAccessibilityTraitKeyboardKeyTecla de teclado
TabBarUIAccessibilityTraitTabBarElemento de barra de abas

Constantes estão disponíveis em UIKit desde iOS 3.0. iOS 14+ adicionou suporte a UIAccessibilityTraits no SwiftUI através do modificador .accessibilityAddTraits().

Traits raros mas úteis

UIAccessibilityTraitAdjustable — para valores ajustáveis (sliders, seletores, controles de volume). O VoiceOver permite deslizar para cima/baixo para alterar o valor com um passo definido via accessibilityIncrement e accessibilityDecrement. UIAccessibilityTraitUpdatesFrequently — para elementos com valores que mudam frequentemente (temporizador, indicador de progresso). O VoiceOver não lê o valor a cada mudança, mas faz uma pausa. UIAccessibilityTraitAllowsDirectInteraction — para elementos com os quais o usuário pode interagir diretamente (teclado, desenho), ignorando gestos do VoiceOver.

Combinação de traits

Um único elemento pode ter vários traits simultaneamente — a combinação é definida usando OR bit a bit (|). Exemplo: um botão atualmente selecionado — Button | Selected. O VoiceOver anunciará: “Selecionado. Filtrado por preço. Botão.”

Definindo traits em código:

swift
filterButton.accessibilityTraits.insert(.button)
filterButton.accessibilityTraits.insert(.selected)

// Ou através de uma máscara:
filterButton.accessibilityTraits = [.button, .selected]

Para UIView personalizado onde o trait não é definido por padrão:

swift
class CustomToggle: UIControl {
    override var accessibilityTraits: UIAccessibilityTraits {
        get {
            if isOn {
                return [.button, .selected]
            } else {
                return .button
            }
        }
        set {}
    }
}

Regra de combinação: não mais que 3-4 traits por elemento. Traits excessivos (por exemplo, Button + Link + Header) tornam o anúncio do VoiceOver muito longo e confuso. Segundo a Apple, “cada propriedade adicional aumenta a carga cognitiva do usuário”.

SwiftUI: Modificadores de traits

No SwiftUI, os traits são definidos usando os modificadores .accessibilityAddTraits() e .accessibilityRemoveTraits(). Exemplo: Text(“Título”).font(.largeTitle).accessibilityAddTraits(.isHeader). O modificador .isHeader adiciona UIAccessibilityTraitHeader. Lista de traits do SwiftUI: .isButton, .isHeader, .isLink, .isSelected, .isImage, .isSearchField, .isKeyboardKey, .isStaticText, .isSummaryElement, .isToggle, .playsSound, .startsMediaSession, .updatesFrequently, .allowsDirectInteraction, .causesPageTurn, .isModal, .tabBar.

Erros típicos ao escolher um trait

StaticText em vez de Button — um controle personalizado que visualmente parece um botão recebe o trait StaticText por padrão. O VoiceOver não oferece um gesto de ativação, então o usuário não pode “pressionar” o elemento. Solução: definir explicitamente .button.

Imagem sem trait — UIImageView com acessibilidade habilitada recebe o trait Image, mesmo que seja na verdade um botão para ampliar uma foto. Atribua .button e Label “Ampliar foto.” De acordo com WWDC 2023, “Deliver an Exceptional Accessibility Experience”, 40% das regressões de acessibilidade em novas versões de aplicativos são causadas precisamente pela incompatibilidade de trait.

Header em cada elemento — o trait Header é destinado a cabeçalhos estruturais da tela. Se cada UILabel for transformado em cabeçalho, o rotor do VoiceOver no modo “Cabeçalhos” se torna inútil — ele parará em cada palavra.

Como corrigir: lista de verificação

  • Cada elemento personalizado interativo recebe o trait Button, Link ou Adjustable
  • Cabeçalhos de seção recebem o trait Header (não StaticText)
  • Botões de imagem recebem o trait Button + Selected quando no estado selecionado
  • Elementos sem gesto — StaticText ou Image (somente leitura)

Bugs de regressão ao substituir UIButton por UIControl

Uma causa comum de perda de trait é a refatoração: um desenvolvedor substitui UIButton por UIControl para exibição personalizada. UIButton automaticamente recebe o trait Button, UIControl não. Após a refatoração, você precisa definir explicitamente accessibilityTraits = .button. Adicione uma verificação na revisão de código: “Se substituiu UIButton por UIControl — verifique o trait.”

Traits e estados dinâmicos

Para elementos com estado mutável (por exemplo, um botão de curtir), o trait deve mudar dinamicamente. No estado “ não curtido” — Button, no estado “curtido” — Button + Selected + Image (se houver um ícone). O VoiceOver muda o anúncio: “Curtir. Botão.” vs “Selecionado. Curtir. Botão.” Use accessibilityValue para transmitir o estado se o trait Selected for insuficiente. Relevante para botões de inscrição, favoritos, filtros e interruptores.

Equivalente Android: role e className

No Android, não há equivalente direto aos traits. Em vez de uma máscara de bits, são usados:

  • className — o valor de AccessibilityNodeInfo.className (android.widget.Button, android.widget.TextView)
  • role — um atributo XML (a função é determinada pelo tipo de View)
  • stateDescription — um equivalente de Selected: adicionar uma descrição de estado (ativado/desativado)

Para Views personalizados no Android, você precisa sobrescrever onInitializeAccessibilityNodeInfo:

kotlin
class CustomButton @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : View(context, attrs) {

    override fun onInitializeAccessibilityNodeInfo(
        info: AccessibilityNodeInfo
    ) {
        super.onInitializeAccessibilityNodeInfo(info)
        info.className = "android.widget.Button"
        info.isClickable = true
    }
}

Desenvolvedores Flutter devem usar o parâmetro semanticsRole no widget Semantics: button, header, image, link, textField e outros. Além disso, semanticsLabel e semanticsHint estão disponíveis — um equivalente completo da tríade iOS Label + Hint + Trait.

Equivalentes web: papel WAI-ARIA

Para versões web de aplicativos móveis (PWA, WebView), o atributo role do WAI-ARIA é usado: role="button", role="heading", role="link". Este é um equivalente direto de accessibilityTraits. Em aplicativos híbridos, verifique se o WebView passa as funções ARIA para a camada de acessibilidade nativa. Para isso, use o protocolo UIAccessibilityContainerDataTable no iOS ou setAccessibilityDelegate no Android. Um WebView com JavaScript habilitado pode não passar as funções ARIA corretamente — teste separadamente.

AccessibilityNodeInfo: Ações adicionais

No Android, você pode adicionar ações personalizadas ao AccessibilityNodeInfo: AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK e ACTION_LONG_CLICK. Isso é equivalente ao trait Button com gestos adicionais. Para sliders, use ACTION_SET_PROGRESS — equivalente ao Adjustable. Para Spinner e DatePicker — ACTION_SET_SELECTION, ACTION_SET_DATE e ACTION_SET_TIME.

Verificação e teste de traits

Xcode Accessibility Inspector é a ferramenta principal para iOS: selecione um elemento e veja o campo Traits. Ele mostrará a lista de traits definidos. O rotor do VoiceOver com o modo “Elementos” permite navegar por todos os controles da tela.

Teste automatizado em Swift para verificar um trait:

swift
func testSubmitButtonTrait() {
    let app = XCUIApplication()
    app.launch()
    let submitButton = app.buttons["Enviar"]
    XCTAssertTrue(submitButton.isEnabled)
    // XCUIElement não fornece acesso direto aos traits
    // Verificação através da ativação de gesto
    submitButton.tap()
    XCTAssertTrue(app.staticTexts["Formulário enviado"].exists)
}

Verificação manual via VoiceOver: ative o VoiceOver, deslize até o elemento, toque duas vezes — o elemento deve ativar se for um Button. Se o elemento não responder ao toque duplo, o trait está incorreto. Use o gesto Rotor para alternar entre modos (“Cabeçalhos”, “Links”, “Botões”) — cada modo mostrará apenas elementos com o trait correspondente.

Teste unitário de traits no iOS

Antes do iOS 14, os testes unitários não tinham acesso direto a accessibilityTraits. A partir do iOS 14, a propriedade está disponível: XCTAssertEqual(customButton.accessibilityTraits, .button). Use isso em testes unitários para verificar controles personalizados. Recomenda-se testar cada novo UIView personalizado quanto à correção do trait, especialmente após refatoração ou mudança de classe pai.

Perguntas Frequentes

Quantos traits podem ser atribuídos a um elemento?

Até 3-4 traits por elemento. Um número maior torna o anúncio do VoiceOver redundante. Use combinações: Button + Selected, Header + StaticText.

Qual é o trait padrão do UIButton?

UIAccessibilityTraitButton. O iOS define automaticamente para todas as instâncias de UIButton. Se você herdar de UIView e simular um botão, o trait deve ser definido manualmente.

Existe um trait “Adjustable” e para que serve?

Sim, UIAccessibilityTraitAdjustable — para elementos com valores ajustáveis (sliders, seletores, contadores). O VoiceOver permite deslizar para cima/baixo para alterar o valor e ler o estado atual.

Como verificar traits no SwiftUI?

Use o modificador .accessibilityAddTraits(): Text(“Título”).font(.title).accessibilityAddTraits(.isHeader). O método funciona no iOS 14+.

O que acontece se eu não definir um trait para um controle personalizado?

O VoiceOver atribuirá o trait None. O elemento não terá uma função — o screen reader lerá apenas o Label sem indicar o tipo. O usuário não saberá se um gesto de ativação está disponível.

Resumo

  • Accessibility Trait — uma máscara de bits UIAccessibilityTraits que define a função de um elemento iOS para o VoiceOver (Button, Header, Link, StaticText e outros)
  • Traits são combinados usando OR bit a bit ([] no Swift), no máximo 3-4 por elemento
  • UIView personalizados devem receber um trait explícito — por padrão pode ser None ou Image
  • No Android, a função é definida via className no AccessibilityNodeInfo, no Flutter — via semanticsRole
  • Um trait incorreto (StaticText para um botão) quebra o cenário do VoiceOver: nenhum gesto de ativação
  • Verifique traits através do Accessibility Inspector no Xcode e do rotor do VoiceOver
  • No SwiftUI, use .accessibilityAddTraits() para configurar traits declarativamente

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também