译自 www.hackingwithswift.com/books/ios-s…
更多内容,欢迎关注公众号 「Swift花园」
喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀
辅助功能介绍
使得你的应用更加易用意味着你需要花费一些步骤,确保每个人都能充分地使用你的应用。例如,如果用户是盲人,那么你的应用就需要能够很好地利用系统的 VoiceOver 功能,确保你的 UI 可以被读出来。
SwiftUI 对于提供了大量功能,因为它的 VStack 和 HStack 布局系统天然形成了视图流。尽管如此,这些功能并非完美的,你总是可以添加一些额外的信息,帮忙 iOS 的辅助功能系统更好地发挥作用。
通常,测试应用的最佳方式是启用 VoiceOver 支持,然后在真实的设备上运行应用 —— 如果你的应用能够很好地配合 VoiceOver 工作,那大概率你有机会超越同类 iOS 应用的平均水平。
言归正传,在这个技术型项目中,我们会涉及一大波辅助功能的技术,然后回顾之前做过的项目,借助辅助功能将它们的体验升级。
现在,先用 Single View App 模板创建一个新的 iOS 应用,你需要在真实的设备上运行这个工程,并且要启用 VoiceOver。
致谢: 在本章的撰写过程中,我需要特别感谢 Robin Kipp 的帮助 —— 他对于他想要我在辅助功能上提及的内容提供了一些详细的建议,包括一些会影响他个人的使用体验的绝佳示例。
用标签标识视图
在这个项目的相关文件中我放了四幅从 Unsplash 下载的照片。Unsplash 的文件名由一个照片ID 和拍摄者的名字构成。把它们拖进 asset catalog,你会发现名称是类似 “ales-krivec-15949” 这样的,这对于文件本身没有问题,事实上对于我们记忆这个资产文件的来源还是有帮助的。但是,它对于屏幕阅读器确实是个问题。
为了开始接触 VoiceOver,我们需要创建一个简单的视图,随机访问 assete catalog 里的四幅照片。把 ContentView 结构体修改成下面这样:
struct ContentView: View {
let pictures = [
"ales-krivec-15949",
"galina-n-189483",
"kevin-horstmann-141705",
"nicolas-tissot-335096"
]
@State private var selectedPicture = Int.random(in: 0...3)
var body: some View {
Image(pictures[selectedPicture])
.resizable()
.scaledToFit()
.onTapGesture {
self.selectedPicture = Int.random(in: 0...3)
}
}
}
逻辑非常简单,但足以演示两个严重的问题。
以防你还没有启用 VoiceOver(旁白),可以到: 设置 > 辅助功能 > 旁白,启用这个功能。
重要: 旁白开关下方就是使用说明。你平常使用的点击和轻扫的功能都不一样了,请仔细阅读说明。
然后在设备上运行应用,然后点击一下照片激活它。仔细听旁白,你会听出两个问题:
- 读出 “Kevin Horstmann one four one seven zero five”,这对于用户来说是没有用处的,因为根本没有描述照片,反而是令人困惑的 —— 长长的数字串很糟糕。
- 读完上面的字符串之后,旁白说了一句 “image”。确实是一张图片,但由于我们添加了
onTapGesture()modifier,图片也作为按钮存在。
以上问题中的第一个是源于 SwiftUI 的一个副作用:它自带一个为用户提供合理辅助行为的特性:给定一个图像,自动使用图像的名称作为旁白的文本。
我们可以借助两个 modifer 修改旁边读取的文本:.accessibility(label:) 和 .accessibility(hint:)。两者都是包含文本视图,但目的不同:
- label 会被立即读出,因此应该是一段可以说清要点的简短文字。比如,这个视图的作用是从用户数据中删除某个项,那么我们可以叫它 “Delete”。
- hint 则在一个短暂的停顿之后被读出来,它应该用于提供视图用途的细节信息。举个例子,“从收件箱中删除一封邮件”。
辅助标签正是第一个问题的解决方案,借助它可以保持图像名不变,让旁白读出其他对用户有用的信息。
首先,给 ContentView 添加一个图片描述的数组:
let labels = [
"Tulips",
"Frozen tree buds",
"Sunflowers",
"Fireworks",
]
然后把下面这个 modifier 添加到 Image:
.accessibility(label: Text(labels[selectedPicture]))
这样一来,不管图像呈现的是什么,旁白都能正确读出标签。当然,如果你的图像不会随机变化,那么可以简单地把标签写死到 modifier 中。
第二个问题是图像被识别为图像,这当然没有错,因为它确实是图像,但是假如我们给它附加了一个手势,它实际上变成了按钮,这时候再识别成图像就没有什么帮助了。
我们可以用另一个 modifier .accessibility(addTraits:) 来解决这个问题。它能提供额外的幕后信息给旁白,描述视图如何工作,以便我们告诉它某个图像实际上也是一个按钮。
.accessibility(addTraits: .isButton)
如果你需要的话,也可以同时移除图像的特征,方法一样简单:
.accessibility(removeTraits: .isImage)
经过这些改变,我们的 UI 可以更加完美地工作:旁白能够读取有关图像内容的有用描述,并且让用户知道它是一个按钮。
我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~