Accessibility Trait — is een eigenschap van een iOS-element die de rol en het gedrag voor VoiceOver bepaalt. De trait vertelt de schermlezer hoe het element moet worden uitgesproken en welke gebaren beschikbaar zijn: of het een knop, koptekst, link of zoekveld is. Volgens Apple UIAccessibilityTraits, 2024 ondersteunt het systeem 15+ constanten die kunnen worden gecombineerd met een bitmasker. Een correct gekozen trait bespaart tot 50% navigatietijd voor VoiceOver-gebruikers.
Belangrijkste punten
Accessibility Trait — een vlag die op een UIView-element wordt gezet om de semantische rol voor VoiceOver aan te geven. De trait is een van de drie componenten van Apple’s accessibility-triade: Label (naam), Hint (beschrijving), Trait (rol). iOS gebruikt het bitmasker UIAccessibilityTraits (UInt64), waarbij elke bit overeenkomt met een specifieke rol. VoiceOver leest de rol na Label en Hint: „Knop Verzenden. Opent formulier“ — „Knop“ is toegevoegd dankzij de trait UIAccessibilityTraitButton.
Standaard krijgt UIButton UIAccessibilityTraitButton, UILabel — UIAccessibilityTraitStaticText, UIImageView — UIAccessibilityTraitImage. Bij het gebruik van aangepaste besturingselementen moet de ontwikkelaar de trait handmatig instellen. Apple Human Interface Guidelines, 2024, noemen dit „een van de meest kritieke stappen bij het waarborgen van accessibility“.
Zonder de juiste trait weet de gebruiker niet welk gebaar toe te passen: enkel tikken (activeren van knop), dubbeltikken (vergroten) of veeggebaar (schakelaar). De trait bepaalt welke gebaren VoiceOver op het element activeert.
UIAccessibilityTraits — is een typealias UInt64. Elke trait is een constante waarin precies één bit is ingesteld. Bijvoorbeeld UIAccessibilityTraitButton = 0x0000000000000001, UIAccessibilityTraitLink = 0x0000000000000002, UIAccessibilityTraitHeader = 0x0000000000000008. Combinatie wordt bereikt via bitsgewijze OF: 0x0001 | 0x0008 = 0x0009. VoiceOver analyseert het masker en bepaalt het gedrag.
iOS biedt meer dan 15 trait-constanten. Laten we de belangrijkste bekijken, die in 90% van de scenario’s worden gebruikt:
| Trait | Constante | VoiceOver-gedrag |
|---|---|---|
| Button | UIAccessibilityTraitButton | Activeren door dubbeltikken |
| Header | UIAccessibilityTraitHeader | Snelle navigatie door kopteksten |
| Link | UIAccessibilityTraitLink | Activeren als link |
| StaticText | UIAccessibilityTraitStaticText | Alleen lezen, zonder activering |
| SearchField | UIAccessibilityTraitSearchField | Zoekveld met speciaal gedrag |
| Image | UIAccessibilityTraitImage | Afbeelding, zonder activeringsgebaar |
| Selected | UIAccessibilityTraitSelected | Status „geselecteerd“ |
| PlaysSound | UIAccessibilityTraitPlaysSound | Speelt geluid bij activering |
| KeyboardKey | UIAccessibilityTraitKeyboardKey | Toets op toetsenbord |
| TabBar | UIAccessibilityTraitTabBar | Tab-balkelement |
De constanten zijn beschikbaar in UIKit sinds iOS 3.0. In iOS 14+ is ondersteuning voor UIAccessibilityTraits in SwiftUI toegevoegd via de modifier .accessibilityAddTraits().
UIAccessibilityTraitAdjustable — voor instelbare waarden (schuifregelaars, kieswijzers, volumeschuifregelaars). VoiceOver maakt vegen omhoog/omlaag mogelijk om de waarde te wijzigen met een stap die is gedefinieerd via accessibilityIncrement en accessibilityDecrement. UIAccessibilityTraitUpdatesFrequently — voor elementen met een vaak veranderende waarde (timer, laadindicator). VoiceOver leest de waarde niet bij elke wijziging, maar neemt een pauze. UIAccessibilityTraitAllowsDirectInteraction — voor elementen waarmee de gebruiker direct kan interacteren (toetsenbord, tekengereedschap), zonder VoiceOver-gebaren.
Een element kan tegelijkertijd meerdere traits hebben — de combinatie wordt gespecificeerd met bitsgewijze OF (|). Voorbeeld: een knop die momenteel is geselecteerd — Button | Selected. VoiceOver zegt: „Geselecteerd. Gefilterd op prijs. Knop“.
Traits instellen in code:
filterButton.accessibilityTraits.insert(.button)
filterButton.accessibilityTraits.insert(.selected)
// Of via masker:
filterButton.accessibilityTraits = [.button, .selected]
Voor aangepaste UIView waar de trait niet standaard is ingesteld:
class CustomToggle: UIControl {
override var accessibilityTraits: UIAccessibilityTraits {
get {
if isOn {
return [.button, .selected]
} else {
return .button
}
}
set {}
}
}
Combinatieregel: niet meer dan 3-4 traits per element. Overmatige traits (bijv. Button + Link + Header) maken de VoiceOver-aankondiging te lang en verwarrend. Volgens Apple „verhoogt elke extra eigenschap de cognitieve belasting van de gebruiker“.
In SwiftUI worden traits ingesteld via de modifiers .accessibilityAddTraits() en .accessibilityRemoveTraits(). Voorbeeld: Text(„Koptekst“).font(.largeTitle).accessibilityAddTraits(.isHeader). De modifier .isHeader voegt UIAccessibilityTraitHeader toe. Lijst van SwiftUI-traits: .isButton, .isHeader, .isLink, .isSelected, .isImage, .isSearchField, .isKeyboardKey, .isStaticText, .isSummaryElement, .isToggle, .playsSound, .startsMediaSession, .updatesFrequently, .allowsDirectInteraction, .causesPageTurn, .isModal, .tabBar.
StaticText in plaats van Button — een aangepast besturingselement dat er visueel uitziet als een knop krijgt standaard de trait StaticText. VoiceOver biedt geen activeringsgebaar, de gebruiker kan het element niet „ indrukken“. Oplossing: stel expliciet .button in.
Image zonder trait — UIImageView met ingeschakelde accessibility krijgt de trait Image, zelfs als het eigenlijk een knop is om een foto te vergroten. Wijs .button en Label „Vergroot foto“ toe. Volgens WWDC 2023, „Deliver an Exceptional Accessibility Experience“ wordt 40% van de accessibility-regressies in nieuwe versies van apps precies veroorzaakt door niet-overeenkomende traits.
Header op elk element — de trait Header is bedoeld voor structurele kopteksten van het scherm. Als je elke UILabel een koptekst maakt, wordt de VoiceOver-rotor in de modus „Kopteksten“ nutteloos — hij stopt bij elk woord.
Veelvoorkomende oorzaak van trait-verlies — refactoring: de ontwikkelaar vervangt UIButton door UIControl voor aangepaste weergave. UIButton krijgt automatisch de trait Button, UIControl — niet. Na refactoring moet expliciet accessibilityTraits = .button worden ingesteld. Voeg een controle toe in code review: „Als je UIButton hebt vervangen door UIControl — controleer de trait“.
Voor elementen met een veranderende toestand (bijv. like-knop) moet de trait dynamisch veranderen. In de status „niet geliket“ — Button, in de status „geliket“ — Button + Selected + Image (als er een pictogram is). VoiceOver verandert de aankondiging: „Vind ik leuk. Knop“ vs „Geselecteerd. Vind ik leuk. Knop“. Gebruik accessibilityValue om de status door te geven als de trait Selected niet voldoende is. Relevant voor abonneer-, favorieten-, filter- en schakelknoppen.
In Android is er geen direct equivalent van traits. In plaats van een bitmasker worden gebruikt:
Voor aangepaste Views in Android moet onInitializeAccessibilityNodeInfo worden overschreven:
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
}
}
Flutter-ontwikkelaars moeten de parameter semanticsRole in de Semantics-widget gebruiken: button, header, image, link, textField en andere. Daarnaast zijn semanticsLabel en semanticsHint beschikbaar — het volledige equivalent van de iOS-triade Label + Hint + Trait.
Voor webversies van mobiele apps (PWA, WebView) wordt het attribuut role uit WAI-ARIA gebruikt: role="button", role="heading", role="link". Dit is het directe equivalent van accessibilityTraits. In hybride apps controleer of WebView ARIA-rollen doorgeeft aan de native accessibility-laag. Gebruik hiervoor het protocol UIAccessibilityContainerDataTable in iOS of setAccessibilityDelegate in Android. WebView met ingeschakelde JavaScript geeft mogelijk ARIA-rollen niet correct door — test apart.
In Android kunnen aangepaste acties worden toegevoegd aan AccessibilityNodeInfo: AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK en ACTION_LONG_CLICK. Dit is het equivalent van de trait Button met extra gebaren. Gebruik voor schuifregelaars ACTION_SET_PROGRESS — equivalent van Adjustable. Voor Spinner en DatePicker — ACTION_SET_SELECTION, ACTION_SET_DATE en ACTION_SET_TIME.
Xcode Accessibility Inspector — het belangrijkste hulpmiddel voor iOS: selecteer het element en bekijk het veld Traits. Het toont de lijst met ingestelde traits. De VoiceOver-rotor in de modus „Elementen“ maakt het mogelijk door alle besturingselementen van het scherm te gaan.
Geautomatiseerde test in Swift voor het controleren van een trait:
func testSubmitButtonTrait() {
let app = XCUIApplication()
app.launch()
let submitButton = app.buttons["Verzenden"]
XCTAssertTrue(submitButton.isEnabled)
// XCUIElement biedt geen directe toegang tot traits
// Controle via activering van gebaar
submitButton.tap()
XCTAssertTrue(app.staticTexts["Formulier verzonden"].exists)
}
Handmatige controle via VoiceOver: schakel VoiceOver in, beweeg je vinger naar het element, tik tweemaal — het element moet worden geactiveerd als het een Button is. Als het element niet reageert op dubbeltikken, is de trait onjuist. Gebruik het Rotor-gebaar om te schakelen tussen modi („Kopteksten“, „Links“, „Knoppen“) — elke modus toont alleen elementen met de bijbehorende trait.
Vóór iOS 14 hadden unit-tests geen directe toegang tot accessibilityTraits. Vanaf iOS 14 is de eigenschap beschikbaar: XCTAssertEqual(customButton.accessibilityTraits, .button). Gebruik dit in modulaire tests voor het controleren van aangepaste besturingselementen. Het wordt aanbevolen om elke nieuwe aangepaste UIView te testen op correctheid van de trait, vooral na refactoring of wijziging van de bovenliggende klasse.
Veelgestelde vragen
Tot 3-4 traits per element. Een groter aantal maakt de VoiceOver-aankondiging overbodig. Gebruik combinaties: Button + Selected, Header + StaticText.
UIAccessibilityTraitButton. iOS stelt deze automatisch in voor alle instanties van UIButton. Als je overerft van UIView en een knop nabootst, moet de trait handmatig worden ingesteld.
Ja, UIAccessibilityTraitAdjustable — voor elementen met een instelbare waarde (schuifregelaars, kieswijzers, tellers). VoiceOver maakt vegen omhoog/omlaag mogelijk om de waarde te wijzigen en leest de huidige status.
Gebruik de modifier .accessibilityAddTraits(): Text(„Koptekst“).font(.title).accessibilityAddTraits(.isHeader). De methode werkt op iOS 14+.
VoiceOver kent de trait None toe. Het element krijgt geen rol — de schermlezer leest alleen Label zonder het type te specificeren. De gebruiker weet niet of het activeringsgebaar beschikbaar is.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook