Accessibility Trait 是 iOS 元素的一个属性,它决定了该元素在 VoiceOver 中的角色和行为。特性告诉屏幕阅读器元素应该如何被朗读以及哪些手势可用:它是按钮、标题、链接还是搜索字段。根据 Apple UIAccessibilityTraits,2024,系统支持 15 个以上的常量,可以通过位掩码组合。正确选择的特性可为 VoiceOver 用户节省多达 50% 的导航时间。
要点
Accessibility Trait — 设置在 UIView 元素上的一个标志,用于指示其在 VoiceOver 中的语义角色。特性是 Apple 无障碍三元组的三个组成部分之一:Label(名称)、Hint(描述)、Trait(角色)。iOS 使用 UIAccessibilityTraits(UInt64)位掩码,其中每个位对应一个特定角色。VoiceOver 在 Label 和 Hint 之后读取角色:“按钮 发送。将打开表单” — “按钮” 是借助 UIAccessibilityTraitButton 特性添加的。
默认情况下,UIButton 获取 UIAccessibilityTraitButton,UILabel — UIAccessibilityTraitStaticText,UIImageView — UIAccessibilityTraitImage。使用自定义控件时,开发人员必须手动设置特性。Apple Human Interface Guidelines,2024 将此称为 “确保无障碍性中最关键的步骤之一”。
没有正确的特性,用户不知道要使用哪种手势:单击(激活按钮)、双击(放大)或滑动手势(开关)。特性决定 VoiceOver 在元素上激活哪些手势。
UIAccessibilityTraits 是 typealias UInt64。每个特性都是一个常量,其中恰好设置了一个位。例如 UIAccessibilityTraitButton = 0x0000000000000001、UIAccessibilityTraitLink = 0x0000000000000002、UIAccessibilityTraitHeader = 0x0000000000000008。组合通过按位或实现:0x0001 | 0x0008 = 0x0009。VoiceOver 分析掩码并确定行为。
iOS 提供超过 15 个特性常量。让我们看看在 90% 的场景中使用的主要特性:
| 特性 | 常量 | VoiceOver 行为 |
|---|---|---|
| Button | UIAccessibilityTraitButton | 通过双击激活 |
| Header | UIAccessibilityTraitHeader | 在标题间快速导航 |
| Link | UIAccessibilityTraitLink | 作为链接激活 |
| StaticText | UIAccessibilityTraitStaticText | 只读,无激活 |
| SearchField | UIAccessibilityTraitSearchField | 具有特殊行为的搜索字段 |
| Image | UIAccessibilityTraitImage | 图像,无激活手势 |
| Selected | UIAccessibilityTraitSelected | “已选定” 状态 |
| PlaysSound | UIAccessibilityTraitPlaysSound | 激活时播放声音 |
| KeyboardKey | UIAccessibilityTraitKeyboardKey | 键盘按键 |
| TabBar | UIAccessibilityTraitTabBar | 标签栏元素 |
这些常量在 UIKit 中从 iOS 3.0 开始可用。在 iOS 14+ 中,通过 .accessibilityAddTraits() 修饰符在 SwiftUI 中添加了对 UIAccessibilityTraits 的支持。
UIAccessibilityTraitAdjustable — 用于可调整的值(滑块、选择器、音量滑块)。VoiceOver 允许向上/向下滑动以通过 accessibilityIncrement 和 accessibilityDecrement 定义的步长更改值。UIAccessibilityTraitUpdatesFrequently — 用于值频繁变化的元素(计时器、加载指示器)。VoiceOver 不会在每次更改时读取值,而是暂停。UIAccessibilityTraitAllowsDirectInteraction — 用于用户可以直接与之交互的元素(键盘、绘图工具),绕过 VoiceOver 手势。
一个元素可以同时拥有多个特性 — 组合通过按位或(|)指定。例如:当前已选定的按钮 — Button | Selected。VoiceOver 会说:“已选定。按价格筛选。按钮”。
在代码中设置特性:
filterButton.accessibilityTraits.insert(.button)
filterButton.accessibilityTraits.insert(.selected)
// 或者通过掩码:
filterButton.accessibilityTraits = [.button, .selected]
对于未默认设置特性的自定义 UIView:
class CustomToggle: UIControl {
override var accessibilityTraits: UIAccessibilityTraits {
get {
if isOn {
return [.button, .selected]
} else {
return .button
}
}
set {}
}
}
组合规则:每个元素不超过 3-4 个特性。过多的特性(例如 Button + Link + Header)会使 VoiceOver 的播报过于冗长和混乱。根据 Apple 的说法,“每个额外的属性都会增加用户的认知负担”。
在 SwiftUI 中,特性通过 .accessibilityAddTraits() 和 .accessibilityRemoveTraits() 修饰符设置。例如:Text(“标题”).font(.largeTitle).accessibilityAddTraits(.isHeader)。.isHeader 修饰符添加 UIAccessibilityTraitHeader。SwiftUI 特性列表:.isButton、.isHeader、.isLink、.isSelected、.isImage、.isSearchField、.isKeyboardKey、.isStaticText、.isSummaryElement、.isToggle、.playsSound、.startsMediaSession、.updatesFrequently、.allowsDirectInteraction、.causesPageTurn、.isModal、.tabBar。
用 StaticText 代替 Button — 视觉上看起来像按钮的自定义控件默认获得 StaticText 特性。VoiceOver 不提供激活手势,用户无法 “按下” 元素。解决方案:显式设置 .button。
无特性的 Image — 启用了无障碍的 UIImageView 会获得 Image 特性,即使它实际上是用于放大照片的按钮。分配 .button 和 “放大照片” 标签。根据 WWDC 2023,“Deliver an Exceptional Accessibility Experience”,应用程序新版本中 40% 的无障碍回归正是由特性不匹配引起的。
每个元素上都用 Header — Header 特性用于屏幕的结构性标题。如果您将每个 UILabel 都设为标题,VoiceOver 转子在 “标题” 模式下将变得毫无用处 — 它会在每个单词处停顿。
特性丢失的常见原因 — 重构:开发人员将 UIButton 替换为 UIControl 以实现自定义显示。UIButton 自动获取 Button 特性,而 UIControl 则不会。重构后需要显式设置 accessibilityTraits = .button。在代码审查中添加检查:“如果将 UIButton 替换为 UIControl — 请检查特性”。
对于状态变化的元素(例如点赞按钮),特性应动态变化。在 “未点赞” 状态下 — Button,在 “已点赞” 状态下 — Button + Selected + Image(如果有图标)。VoiceOver 更改播报:“喜欢。按钮” 对比 “已选定。喜欢。按钮”。如果 Selected 特性不足,请使用 accessibilityValue 传递状态。适用于订阅、收藏、筛选和开关按钮。
在 Android 中没有特性的直接对应。代替位掩码使用的是:
对于 Android 中的自定义 View,需要重写 onInitializeAccessibilityNodeInfo:
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 开发人员应在 Semantics 小部件中使用 semanticsRole 参数:button、header、image、link、textField 等。此外,还有 semanticsLabel 和 semanticsHint — iOS 三元组 Label + Hint + Trait 的完整对应。
对于移动应用的 Web 版本(PWA、WebView),使用 WAI-ARIA 的 role 属性:role="button"、role="heading"、role="link"。这是 accessibilityTraits 的直接对应。在混合应用中,检查 WebView 是否将 ARIA 角色传递到原生无障碍层。为此,在 iOS 中使用 UIAccessibilityContainerDataTable 协议,在 Android 中使用 setAccessibilityDelegate。启用 JavaScript 的 WebView 可能无法正确传递 ARIA 角色 — 请单独测试。
在 Android 中,可以向 AccessibilityNodeInfo 添加自定义操作:AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK 和 ACTION_LONG_CLICK。这是具有额外手势的 Button 特性的对应。对于滑块,使用 ACTION_SET_PROGRESS — Adjustable 的对应。对于 Spinner 和 DatePicker — ACTION_SET_SELECTION、ACTION_SET_DATE 和 ACTION_SET_TIME。
Xcode Accessibility Inspector — iOS 的主要工具:选择元素并查看 Traits 字段。它将显示已设置特性的列表。处于 “元素” 模式的 VoiceOver 转子可以遍历屏幕上的所有控件。
用于检查特性的 Swift 自动化测试:
func testSubmitButtonTrait() {
let app = XCUIApplication()
app.launch()
let submitButton = app.buttons["发送"]
XCTAssertTrue(submitButton.isEnabled)
// XCUIElement 不提供对特性的直接访问
// 通过手势激活进行检查
submitButton.tap()
XCTAssertTrue(app.staticTexts["表单已发送"].exists)
}
手动通过 VoiceOver 检查:启用 VoiceOver,将手指移到元素上,双击 — 如果是 Button,元素应激活。如果元素对双击没有反应,则特性不正确。使用 Rotor 手势在模式之间切换(“标题”、“链接”、“按钮”)— 每种模式仅显示具有相应特性的元素。
在 iOS 14 之前,单元测试无法直接访问 accessibilityTraits。从 iOS 14 开始,该属性可用:XCTAssertEqual(customButton.accessibilityTraits, .button)。在模块测试中使用它来检查自定义控件。建议测试每个新的自定义 UIView 的特性正确性,尤其是在重构或更改父类之后。
常见问题解答
每个元素最多 3-4 个特性。数量过多会使 VoiceOver 播报变得冗余。使用组合:Button + Selected、Header + StaticText。
UIAccessibilityTraitButton。iOS 会自动为所有 UIButton 实例设置它。如果您继承自 UIView 并模拟按钮,则需要手动设置特性。
是的,UIAccessibilityTraitAdjustable — 用于具有可调整值的元素(滑块、选择器、计数器)。VoiceOver 允许向上/向下滑动以更改值并读取当前状态。
使用 .accessibilityAddTraits() 修饰符:Text(“标题”).font(.title).accessibilityAddTraits(.isHeader)。该方法在 iOS 14+ 上有效。
VoiceOver 将分配 None 特性。元素将不会获得角色 — 屏幕阅读器将仅读取 Label 而不指定类型。用户将不知道激活手势是否可用。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。