Content Description — 一项无障碍属性,它将非文本内容的文本描述传递给辅助技术。在 iOS 中,这是 UIView 的 accessibilityHint 属性;在 Android 中,它是 XML 标记中的 contentDescription。根据 W3C WCAG 2.2, 2023 的数据,缺少非文本内容的文本替代是移动应用中常见的无障碍违规之一。正确填写的描述使应用对于使用 VoiceOver 和 TalkBack 的视障人士是可达的。
要点
Content Description — 界面元素的一个字符串属性,它将视觉内容的文本表示传递给辅助技术。屏幕阅读器(iOS 中的 VoiceOver,Android 中的 TalkBack)朗读描述,而不是尝试视觉识别元素。描述应用于没有文本层的图像、图标、图表、自定义控件和任何非文本元素。
根据 Google Material Design, 2024 的数据,没有 contentDescription 的元素违反了 WCAG 1.1.1(非文本内容)规则。Accessibility Scanner 检查显示,商店应用中高达 40% 的图标没有描述。VoiceOver 用户只听到「图像」或「按钮」而没有具体说明——这样的界面变得无法用于导航。
Content Description 不替代元素的可见文本。如果按钮包含文本标签「发送」,则不需要额外描述——屏幕阅读器会读取文本。对于图像、图标和输入字段,描述是必需的。
Accessibility Scanner(Android)和 Xcode Accessibility Inspector(iOS)工具自动检查描述的存在。建议在发布前在每个屏幕上执行这些检查。
视障用户依赖 VoiceOver 来理解界面。如果购物车图标没有描述,他只会听到「按钮」。为了知道按钮的功能,他必须盲目点击——存在不可逆操作的风险。描述「从购物车中移除产品」在一秒钟内解决了这个问题。
具有临时限制的用户(户外强光、屏幕破裂)也使用 VoiceOver。根据 Apple Accessibility Report, 2023,大约 20% 的 VoiceOver 用户没有永久性视障——他们根据情况启用此功能。
WCAG 1.1.1(A 级)标准要求每个非文本内容都有文本替代。例外:装饰性内容、仅用于视觉设计或不承载信息的内容。装饰性测试:如果删除元素,页面的含义会改变吗?如果不会——可以将其隐藏在屏幕阅读器之外。
Accessibility Label(iOS 中的 accessibilityLabel)——屏幕阅读器在聚焦时发音的元素名称。Content Description(iOS 中的 accessibilityHint)——在名称之后朗读的额外说明,告知操作的结果。
区别在「购物车」按钮示例中清晰可见。Label:「购物车」。Description:「将打开订单屏幕」。VoiceOver 说:「购物车。将打开订单屏幕」。如果只设置了 Label,用户将不知道点击后会发生什么。
| 属性 | iOS | Android | 用途 |
|---|---|---|---|
| Label | accessibilityLabel | contentDescription | 元素名称(按钮、字段、图像) |
| Description | accessibilityHint | contentDescription(扩展) | 操作或含义的说明 |
| Trait | accessibilityTraits | role / className | 元素角色(按钮、标题) |
规则:Label 回答「这是什么?」的问题,Description 回答「会发生什么?」。在 Android 中,contentDescription 可以承载两个角色,但实践中更好分开:使用「[名称],[说明]」的串联。
对于复杂手势(滑动删除、长按上下文菜单),accessibilityHint 是必需的。VoiceOver 用户不知道未描述的手势。在元素的 hint 中指出:「向左滑动以删除」。
在 iOS 平台上,accessibilityHint 通过 UIView 或 NSObject 的同名属性设置。值——最多 80 个字符的字符串。如果开启了详细描述模式(在 VoiceOver 设置中——「Verbosity」),VoiceOver 会在 label 之后朗读 hint。
为自定义按钮设置 hint 的示例:
import UIKit
class CustomButton: UIButton {
override func awakeFromNib() {
super.awakeFromNib()
self.accessibilityLabel = "添加至收藏"
self.accessibilityHint = "将产品保存到收藏列表"
}
}
对于没有文本内容的 UIImageView,必须设置 isAccessibilityElement = true 和 accessibilityHint:
let imageView = UIImageView(image: UIImage(named: "chart-sales"))
imageView.isAccessibilityElement = true
imageView.accessibilityHint = "上季度销售图表"
VoiceOver 读取:「上季度销售图表」。如果 hint 为空——只读「图像」。Apple HIG, 2024 建议不要在 hint 中使用「按下」或「触摸」等动词——VoiceOver 会自动添加手势指令。
在 SwiftUI 中,hint 通过链式修饰符设置:
Image(systemName: "trash")
.accessibilityLabel("删除")
.accessibilityHint("彻底删除所选元素")
SwiftUI 自动为复合视图组合修饰符。如果 Image 位于 Button 内部,SwiftUI 使用按钮的 label 作为主要的 accessibilityLabel。
在 Android 中,contentDescription 在 XML 标记中或以编程方式通过 setContentDescription() 设置。TalkBack 在聚焦元素时朗读描述。
XML 示例:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_search"
android:contentDescription="产品搜索" />
动态元素的编程设置:
binding.iconSearch.contentDescription =
"搜索。将打开带筛选器的搜索界面"
对于装饰性图像(分隔符、背景、装饰性图标),设置 contentDescription = "@null" 或 setContentDescription(null)——TalkBack 将跳过此类元素。在 XML 中:android:contentDescription="@null"。空字符串 "" 不起作用——TalkBack 仍然会说「图像」。
对于 ImageButton 始终设置 contentDescription——TalkBack 看不到图像上的文本。对于 CheckBox,描述应动态变化:「已选择」/「未选择」而不是静态描述。在状态监听器中使用 setContentDescription。
信息性——描述应传达含义,而非外观。不是「带勾的蓝色图标」,而是「产品已添加到购物车」。屏幕阅读器不关心颜色——它关心结果。
简洁性——最佳长度为 2–4 个词(最多 80 个字符)。长描述会减慢导航:VoiceOver 按顺序朗读,每个词是用户的一秒钟时间。根据 Apple WWDC 2023, 「Accessibility by Design」,朗读超过 5 秒的短语会中断认知流。
唯一性——一个屏幕上不应有两个具有相同描述的元素。用户将无法区分聚焦第一个和第二个元素会产生什么结果。如果有多个「购买」按钮——添加标识符:「购买 iPhone 15」、「购买 iPhone 15 Pro」。
本地化——Content Description 被翻译为应用支持的所有语言。描述本地化错误是 App Store 中 Accessibility Review 失败的常见原因之一。
Nielsen Norman Group, 2024 的研究表明,屏幕阅读器的最佳描述长度为 3–5 个词(最多 50 个字符)。更长的描述会将导航速度降低 30%,因为用户必须等待朗读完成后才能进行下一步。
冗余——描述重复可见文本。如果按钮包含文本「发送」,不要设置 accessibilityHint = 「发送按钮」。VoiceOver 会自动读取文本,而 hint 会增加不必要的噪音。
与 Label 混淆——对文本按钮使用 contentDescription 而不是 label。在 iOS 中,accessibilityLabel 应与按钮文本匹配(如果文本已可见则为空),而 hint 仅解释操作。根据 Google Testing Blog, 2024,Play Store 中 23% 的检查应用具有重复的描述。
忽略动态性——描述在状态变化时不会更新。例如,Wi-Fi 开关的描述在开启后仍保持「开启 Wi-Fi」。正确做法:通过观察状态将描述动态更改为「关闭 Wi-Fi」。
设计更新(更换图标、重新排列元素)后,Content Description 经常丢失。原因:设计师更换了图像,开发人员未检查新资产的无障碍属性。解决方案:将无障碍检查作为 code review 的强制步骤——添加带有「Content Description 已更新?」项的检查清单。
func testContentDescriptionExists() {
let app = XCUIApplication()
app.launch()
let image = app.images["chart-sales"]
XCTAssertNotNil(image.label)
XCTAssertGreaterThan(image.label.count, 0)
}
常见问题
VoiceOver 或 TalkBack 用户将只听到「图像」或「按钮」——没有说明用途。这违反了 WCAG 1.1.1,使应用对视障人士不可访问。
不需要。如果按钮包含文本标签,VoiceOver 会自动读取它。描述(accessibilityHint)可以添加以说明点击的结果,但 Label 不需要。
在 iOS 中设置 isAccessibilityElement = false。在 Android 中设置 contentDescription = "@null"。屏幕阅读器将完全跳过此类元素,不发出声音。
在 iOS 中使用 NSLocalizedString 处理 accessibilityHint,在 Android 中通过 @string/ 使用字符串资源。所有支持的语言都必须翻译描述。
添加检查所有 ImageView 描述存在的 UI 测试。在 iOS 中使用 XCUIApplication,在 Android 中使用 Espresso 的 AccessibilityCheckRule。Accessibility Scanner 可以通过命令行在 CI 中运行。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。