Swift用于旁白识别的隐藏和分组视图标签
Swift用于旁白识别的隐藏和分组视图标签

Swift用于旁白识别的隐藏和分组视图标签

隐藏视图标签

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

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注