Accessibility Trait — är en egenskap hos ett iOS-element som bestämmer dess roll och beteende för VoiceOver. Trait berättar för skärmläsaren hur elementet ska uttalas och vilka gester som är tillgängliga: om det är en knapp, rubrik, länk eller sökfält. Enligt Apple UIAccessibilityTraits, 2024 stöder systemet 15+ konstanter som kan kombineras med en bitmask. Ett korrekt valt trait sparar upp till 50% av navigeringstiden för VoiceOver-användare.
Huvudpunkter
Accessibility Trait — en flagga som sätts på ett UIView-element för att indikera dess semantiska roll för VoiceOver. Trait är en av tre komponenter i Apples tillgänglighetstriad: Label (namn), Hint (beskrivning), Trait (roll). iOS använder bitmasken UIAccessibilityTraits (UInt64), där varje bit motsvarar en specifik roll. VoiceOver läser rollen efter Label och Hint: “Knapp Skicka. Öppnar formulär” — “Knapp” lades till tack vare trait UIAccessibilityTraitButton.
Som standard får UIButton UIAccessibilityTraitButton, UILabel — UIAccessibilityTraitStaticText, UIImageView — UIAccessibilityTraitImage. Vid användning av anpassade kontroller är utvecklaren skyldig att manuellt ställa in trait. Apple Human Interface Guidelines, 2024, kallar detta “ett av de mest kritiska stegen för att säkerställa tillgänglighet”.
Utan rätt trait vet användaren inte vilken gest som ska tillämpas: enkel tryckning (aktivering av knapp), dubbeltryckning (förstoring) eller svepgest (omkopplare). Trait avgör vilka gester VoiceOver aktiverar på elementet.
UIAccessibilityTraits — är en typealias UInt64. Varje trait är en konstant där exakt en bit är inställd. Till exempel UIAccessibilityTraitButton = 0x0000000000000001, UIAccessibilityTraitLink = 0x0000000000000002, UIAccessibilityTraitHeader = 0x0000000000000008. Kombination uppnås via bitvis OR: 0x0001 | 0x0008 = 0x0009. VoiceOver analyserar masken och bestämmer beteendet.
iOS tillhandahåller mer än 15 trait-konstanter. Låt oss titta på de viktigaste, som används i 90% av scenarierna:
| Trait | Konstant | VoiceOver-beteende |
|---|---|---|
| Button | UIAccessibilityTraitButton | Aktivering genom dubbeltryck |
| Header | UIAccessibilityTraitHeader | Snabb navigering genom rubriker |
| Link | UIAccessibilityTraitLink | Aktivering som länk |
| StaticText | UIAccessibilityTraitStaticText | Endast läsning, utan aktivering |
| SearchField | UIAccessibilityTraitSearchField | Sökfält med särskilt beteende |
| Image | UIAccessibilityTraitImage | Bild, utan aktiveringsgest |
| Selected | UIAccessibilityTraitSelected | Status “vald” |
| PlaysSound | UIAccessibilityTraitPlaysSound | Spelar ljud vid aktivering |
| KeyboardKey | UIAccessibilityTraitKeyboardKey | Tangent på tangentbord |
| TabBar | UIAccessibilityTraitTabBar | Flikfältselement |
Konstanterna är tillgängliga i UIKit sedan iOS 3.0. I iOS 14+ lades stöd för UIAccessibilityTraits i SwiftUI till via modifieraren .accessibilityAddTraits().
UIAccessibilityTraitAdjustable — för justerbara värden (reglage, väljare, volymreglage). VoiceOver tillåter svep uppåt/nedåt för att ändra värdet med steg som definieras via accessibilityIncrement och accessibilityDecrement. UIAccessibilityTraitUpdatesFrequently — för element med ofta ändrande värde (timer, laddningsindikator). VoiceOver läser inte värdet vid varje ändring, utan tar en paus. UIAccessibilityTraitAllowsDirectInteraction — för element som användaren kan interagera direkt med (tangentbord, ritverktyg), utan VoiceOver-gester.
Ett element kan ha flera traits samtidigt — kombinationen specificeras med bitvis OR (|). Exempel: en knapp som för närvarande är vald — Button | Selected. VoiceOver säger: “Vald. Filtrerad efter pris. Knapp”.
Ställa in traits i kod:
filterButton.accessibilityTraits.insert(.button)
filterButton.accessibilityTraits.insert(.selected)
// Eller via mask:
filterButton.accessibilityTraits = [.button, .selected]
För anpassade UIView där trait inte är inställd som standard:
class CustomToggle: UIControl {
override var accessibilityTraits: UIAccessibilityTraits {
get {
if isOn {
return [.button, .selected]
} else {
return .button
}
}
set {}
}
}
Kombinationsregel: inte mer än 3-4 traits per element. Överdrivna traits (t.ex. Button + Link + Header) gör VoiceOver-meddelandet för långt och förvirrande. Enligt Apple “ökar varje extra egenskap den kognitiva belastningen för användaren”.
I SwiftUI ställs traits in via modifierarna .accessibilityAddTraits() och .accessibilityRemoveTraits(). Exempel: Text(“Rubrik”).font(.largeTitle).accessibilityAddTraits(.isHeader). Modifieraren .isHeader lägger till UIAccessibilityTraitHeader. Lista över SwiftUI-traits: .isButton, .isHeader, .isLink, .isSelected, .isImage, .isSearchField, .isKeyboardKey, .isStaticText, .isSummaryElement, .isToggle, .playsSound, .startsMediaSession, .updatesFrequently, .allowsDirectInteraction, .causesPageTurn, .isModal, .tabBar.
StaticText istället för Button — en anpassad kontroll som visuellt ser ut som en knapp får som standard trait StaticText. VoiceOver erbjuder ingen aktiveringsgest, användaren kan inte “trycka på” elementet. Lösning: ställ explicit in .button.
Image utan trait — UIImageView med aktiverad tillgänglighet får trait Image, även om det egentligen är en knapp för att förstora ett foto. Tilldela .button och Label “Förstora foto”. Enligt WWDC 2023, “Deliver an Exceptional Accessibility Experience” orsakas 40% av tillgänglighetsregressioner i nya appversioner just av trait-avvikelse.
Header på varje element — trait Header är avsedd för strukturella rubriker på skärmen. Om du gör varje UILabel till en rubrik blir VoiceOver-rotorn i läget “Rubriker” oanvändbar — den stannar vid varje ord.
Vanlig orsak till trait-förlust — refaktorering: utvecklaren ersätter UIButton med UIControl för anpassad visning. UIButton får automatiskt trait Button, UIControl — inte. Efter refaktorering måste accessibilityTraits = .button ställas in explicit. Lägg till en kontroll i kodgranskning: “Om du ersatte UIButton med UIControl — kontrollera trait”.
För element med föränderligt tillstånd (t.ex. like-knapp) bör trait ändras dynamiskt. I tillståndet “gillas inte” — Button, i tillståndet “gillas” — Button + Selected + Image (om det finns ikon). VoiceOver ändrar meddelandet: “Gilla. Knapp” vs “Vald. Gilla. Knapp”. Använd accessibilityValue för att förmedla tillståndet om trait Selected inte räcker. Tillämpligt för prenumerations-, favorit-, filter- och omkopplarknappar.
I Android finns det ingen direkt motsvarighet till traits. Istället för bitmask används:
För anpassade Views i Android måste onInitializeAccessibilityNodeInfo åsidosättas:
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-utvecklare bör använda parametern semanticsRole i Semantics-widgeten: button, header, image, link, textField och andra. Dessutom finns semanticsLabel och semanticsHint — fullständig motsvarighet till iOS-triaden Label + Hint + Trait.
För webbversioner av mobilappar (PWA, WebView) används attributet role från WAI-ARIA: role="button", role="heading", role="link". Detta är den direkta motsvarigheten till accessibilityTraits. I hybridappar kontrollera att WebView förmedlar ARIA-roller till det inbyggda tillgänglighetslagret. Använd protokollet UIAccessibilityContainerDataTable i iOS eller setAccessibilityDelegate i Android för detta. WebView med aktiverad JavaScript kanske inte förmedlar ARIA-roller korrekt — testa separat.
I Android kan anpassade åtgärder läggas till i AccessibilityNodeInfo: AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK och ACTION_LONG_CLICK. Detta är motsvarigheten till trait Button med ytterligare gester. För reglage använd ACTION_SET_PROGRESS — motsvarighet till Adjustable. För Spinner och DatePicker — ACTION_SET_SELECTION, ACTION_SET_DATE och ACTION_SET_TIME.
Xcode Accessibility Inspector — huvudverktyget för iOS: välj elementet och titta på fältet Traits. Det visar listan över inställda traits. VoiceOver-rotorn i läget “Element” gör det möjligt att gå igenom alla kontroller på skärmen.
Automatiserat test i Swift för att kontrollera trait:
func testSubmitButtonTrait() {
let app = XCUIApplication()
app.launch()
let submitButton = app.buttons["Skicka"]
XCTAssertTrue(submitButton.isEnabled)
// XCUIElement ger inte direkt åtkomst till traits
// Kontroll via gestaktivering
submitButton.tap()
XCTAssertTrue(app.staticTexts["Formulär skickat"].exists)
}
Manuell kontroll via VoiceOver: aktivera VoiceOver, för fingret till elementet, tryck två gånger — elementet bör aktiveras om det är en Button. Om elementet inte reagerar på dubbeltryck är trait felaktig. Använd Rotor-gesten för att växla mellan lägen (“Rubriker”, “Länkar”, “Knappar”) — varje läge visar endast element med motsvarande trait.
Före iOS 14 hade unit-tester inte direkt åtkomst till accessibilityTraits. Från och med iOS 14 är egenskapen tillgänglig: XCTAssertEqual(customButton.accessibilityTraits, .button). Använd detta i modulära tester för att kontrollera anpassade kontroller. Det rekommenderas att testa varje ny anpassad UIView för trait-korrekthet, särskilt efter refaktorering eller ändring av överordnad klass.
Vanliga frågor
Upp till 3-4 traits per element. Ett större antal gör VoiceOver-meddelandet överflödigt. Använd kombinationer: Button + Selected, Header + StaticText.
UIAccessibilityTraitButton. iOS ställer automatiskt in den för alla instanser av UIButton. Om du ärver från UIView och simulerar en knapp måste trait ställas in manuellt.
Ja, UIAccessibilityTraitAdjustable — för element med justerbart värde (reglage, väljare, räknare). VoiceOver tillåter svep uppåt/nedåt för att ändra värdet och läser aktuellt tillstånd.
Använd modifieraren .accessibilityAddTraits(): Text(“Rubrik”).font(.title).accessibilityAddTraits(.isHeader). Metoden fungerar på iOS 14+.
VoiceOver tilldelar trait None. Elementet får ingen roll — skärmläsaren läser bara Label utan att ange typ. Användaren vet inte om aktiveringsgesten är tillgänglig.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också