隐藏视图标签
Image(decorative:) 是 SwiftUI 中用于创建无障碍友好的图片的初始化方法,专门用于展示那些不需要屏幕阅读器朗读描述的图片。
当图片是纯装饰性的,并且不会对用户理解界面内容产生任何影响时,可以使用 Image(decorative:)。
屏幕阅读器会忽略这些图片,不会尝试为它们生成朗读描述,从而减少用户的无关信息干扰。
Image(decorative: String, bundle: Bundle?)
1、decorative:
提供图片的名称(字符串),与普通的 Image(_:) 初始化器一样,但会告诉屏幕阅读器忽略这张图片。
2、bundle:
指定图片资源所在的 Bundle,默认值为 nil,表示从主应用程序包中加载图片。
@State private var name = ""
var body: some View {
Text(name)
.accessibilityLabel("Name")
Image(decorative:"fangjunyu")
.resizable()
.scaledToFit()
.onTapGesture {
name = "fangjunyu"
}
}
在这段代码中,当点击照片时,name会被赋值为 “fangjunyu”。当开启辅助功能旁白后,iOS设备不会识别该照片,这也意味着照片和点击手势都不会被识别触发。
同时,也可以通过accessibilityHidden()修饰符,实现图像或其他视图在辅助功能中的显示与隐藏:
Image("fangjunyu")
.accessibilityHidden(true)
这意味着Image(“fangjunyu”)被无障碍功能所隐藏。
.accessibilityHidden(Bool)
参数:
Bool:布尔值,表示是否隐藏视图对辅助功能工具的可见性。
true:从无障碍功能中隐藏该视图。
false:确保该视图对辅助功能工具可见(默认行为)。
功能:
1、屏蔽无关视图:对于辅助功能用户不需要关注的内容,可以通过设置 accessibilityHidden(true) 来隐藏。
2、避免冗余:当屏幕阅读器已经通过其他方式传达了相同信息,可以隐藏冗余的视图。
3、定制无障碍体验:根据应用逻辑动态调整哪些视图需要对辅助功能可见。
在实际应用中,如果将视图放置在屏幕之外以致用户当前看不到它,那么也应该将其标记为 VoiceOver 无法访问。
否则就会出现旁白模式下的空白视图:
例如在刷拼多多短视频时,使用旁白功能,会发现金币左侧存在大量的1-9数字。在未设置辅助功能旁白的情况下,无法预览这些信息,但是如果使用旁白功能,则会发现有很多数字,这里应该得到隐藏。
分组视图标签
VStack {
Text("Your score is")
Text("1000")
.font(.title)
}
在这段代码中,旁白会视为两个不相关的文本视图,但实际想要展示的是,这两个Text视图为同一个内容,因此可以使用accessibilityElement(children:)修饰符。
将两个Text视图组合成一个可访问性元素。
VStack {
Text("Your score is")
Text("1000")
.font(.title)
}
.accessibilityElement(children: .combine)
添加accessibilityLabel(可访问性标签)后,VStack的内容不会单独阅读,而是只阅读accessibilityLabel中的内容。
VStack {
Text("Your score is")
Text("1000")
.font(.title)
}
.accessibilityElement(children: .combine)
.accessibilityLabel("Your score is 123")
这是因为,虽然两个Text视图生成了父视图无障碍描述,但是被accessibilityLabel(可访问性标签)覆盖,导致只阅读了accessibilityLabel(可访问性标签)的内容。
如果使用accessibilityElement(children: .ignore),则表示子视图不会生成父视图的无障碍描述:
.accessibilityElement(children: .ignore)
例如:
VStack {
Text("Your score is")
Text("1000")
.font(.title)
}
.accessibilityElement(children: .ignore)
.accessibilityLabel("Your score is 789")
这段代码的两个Text不会生成父视图的无障碍描述,因此只会阅读accessibilityLabel(可访问性标签)中的内容。
无论使用下面的哪一个方法,都只会阅读accessibilityLabel(可访问性标签)中的内容。
.accessibilityElement(children: .combine) // 子视图组合生成父视图无障碍描述
.accessibilityElement(children: .ignore) // 子视图组合不生成父视图无障碍描述
当删除accessibilityLabel(可访问性标签)后,就可以发现后者不会被旁白读取,因为没有生成父视图的无障碍描述:
VStack {
Text("Your score is") // 旁白正常阅读
Text("1000") // 旁白正常阅读
.font(.title)
}
.accessibilityElement(children: .combine)
VStack {
Text("Your score is") // 旁白不会阅读
Text("1000") // 旁白不会阅读
.font(.title)
}
.accessibilityElement(children: .ignore)
值得注意的是,.accessibilityElement(children: .ignore) 是默认行为。例如直接调用
.accessibilityElement()
而不传递任何参数,那么它的默认参数是 .ignore。.ignore 意味着视图的子视图不会被合并到父视图的无障碍描述中,且子视图的无障碍信息将被忽略。
如果需要忽略子视图的无障碍信息而直接指定父视图的无障碍描述,省略参数即可。
除了.combine(子视图合并到父视图的无障碍描述)和.ignore(忽略子视图合并到父视图的无障碍描述)以外,还有.contain(子视图需要单独保存详细信息):
VStack {
Text("Item 1")
Text("Item 2")
Text("Item 3")
}
.accessibilityElement(children: .contain)
每个子视图都会单独作为无障碍元素。
屏幕阅读器朗读每个文本的内容,例如 “Item 1”,“Item 2”,“Item 3”。
添加. contain和不添加accessibilityElement阅读上没有区别,这是因为默认情况下,VStack 的子视图就已经是独立的无障碍元素,这与 .accessibilityElement(children: .contain) 的效果一致。
所以,只有当使用.combine 或 .ignore时,行为才会发生变化。
适用场景
1、.combine:
当视图有多个子视图,但它们逻辑上应该被视为一个单一的信息单元时。
例如,一个描述性文字和图片组合。
2、.ignore:
当父视图想完全替代子视图在无障碍树中的表现时。
例如,隐藏子视图的无障碍信息,仅提供父视图的摘要信息。
3、.contain:
当子视图需要单独朗读以保留其详细信息时。
例如,列表中的多个独立元素。
注意事项
1、.accessibilityElement(children:) 影响无障碍树的结构和表现,合理使用可以优化用户体验,但滥用可能导致信息丢失或不一致。
2、配合其他无障碍修饰符(如 .accessibilityLabel、.accessibilityHint)使用,可以提供更加直观和有意义的描述。
总结
.accessibilityElement(children:) 是控制无障碍元素行为的关键修饰符,能够根据实际需求灵活调整父子视图的朗读方式,从而提升应用的无障碍体验。
参考文章
Hiding and grouping accessibility data:https://www.hackingwithswift.com/books/ios-swiftui/hiding-and-grouping-accessibility-data