Hacking with iOS: SwiftUI Edition

SwiftUI:辅助功能——项目优化示例

2020-09-03  本文已影响0人  韦弦Zhy

\color{red}{\Large \mathbf{Hacking \quad with \quad iOS: SwiftUI \quad Edition}}

{\Large \mathbf{辅助功能}}

{\Large \mathbf{Accessibility}}

优化猜国旗项目

项目2 猜国旗项目中,我们制作了Guess the Flag,它显示了三个标志图片,并要求用户猜测是哪个。好吧,根据您现在对VoiceOver的了解,您可以发现我们游戏中的致命缺陷吗?

没错:SwiftUI的默认行为是读取图像名称作为其VoiceOver标签,这意味着使用VoiceOver的任何人都可以拿到我们的三个国旗的名字,然后选择正确的。

要解决此问题,我们需要为每个标志添加文本描述,并对其进行足够详细的描述,以使了解它们的人可以正确猜出它们,但是当然不必实际给出国家名称。

如果您打开此项目的副本,则会看到它是使用一组国家名称编写的,如下所示:

@State private var countries = ["Estonia", "France", "Germany", "Ireland", "Italy", "Nigeria", "Poland", "Russia", "Spain", "UK", "US"].shuffled()

因此,在此处附加标签的最简单方法——不需要我们更改任何代码的方法——就是创建一个字典,以国家/地区名称作为键,将可访问性标签作为值,像这样。请将其添加到ContentView

let labels = [
    "Estonia": "Flag with three horizontal stripes of equal size. Top stripe blue, middle stripe black, bottom stripe white",
    "France": "Flag with three vertical stripes of equal size. Left stripe blue, middle stripe white, right stripe red",
    "Germany": "Flag with three horizontal stripes of equal size. Top stripe black, middle stripe red, bottom stripe gold",
    "Ireland": "Flag with three vertical stripes of equal size. Left stripe green, middle stripe white, right stripe orange",
    "Italy": "Flag with three vertical stripes of equal size. Left stripe green, middle stripe white, right stripe red",
    "Nigeria": "Flag with three vertical stripes of equal size. Left stripe green, middle stripe white, right stripe green",
    "Poland": "Flag with two horizontal stripes of equal size. Top stripe white, bottom stripe red",
    "Russia": "Flag with three horizontal stripes of equal size. Top stripe white, middle stripe blue, bottom stripe red",
    "Spain": "Flag with three horizontal stripes. Top thin stripe red, middle thick stripe gold with a crest on the left, bottom thin stripe red",
    "UK": "Flag with overlapping red and white crosses, both straight and diagonally, on a blue background",
    "US": "Flag with red and white stripes of equal size, with white stars on a blue background in the top-left corner"
]

现在我们需要做的就是将accessibility(label:)修饰符添加到标志图像。我意识到这听起来很简单,但是代码必须要做四件事:

  1. 使用self.countries [number]获取当前标志的国家/地区名称。
  2. 使用该名称作为self.labels的键。
  3. 如果国家/地区名称在字典中不存在,请提供一个字符串作为默认值。(这永远都不会发生,但是安全无害!)
  4. 将最终字符串转换为文本视图。

组合这四点在一起,将这个修饰符直接放在标记图像其余修饰符的下面:

.accessibility(label: Text(self.labels[self.countries[number], default: "Unknown flag"]))

现在,如果您再次运行游戏,则无论您是否使用VoiceOver,您都会看到它实际上是一个游戏。这就是无障碍访问的核心:无论访问需求如何,每个人都可以立即玩此游戏。

优化Word Scramble 项目

项目5中,我们构建了Word Scramble,该游戏向用户提供了一个随机的8个字母的单词,并且不得不使用其字母生成新单词。这通常可以在VoiceOver上很好地发挥作用:应用程序的任何部分都无法访问,尽管这并不意味着我们无法做得更好。

要查看明显的痛点,请尝试添加一个单词。您会看到它滑到提示下方的表格中,但是如果您使用VoiceOver轻敲它,您会发现它的阅读效果不佳:字母计数被读为“五个圆圈”,而文本是一个单独的元素。

有几种方法可以改善此问题,但最好的办法是将这两个项目都设为一个单独的组,让VoiceOver忽略这些内容,然后为整个组添加一个包含更自然描述的标签。

我们当前的代码如下:

List(usedWords, id: \.self) {
    Image(systemName: "\($0.count).circle")
    Text($0)
}

这依赖于隐式HStack来将图像和文本并排放置。因此,要解决此问题,我们需要创建一个显式的HStack,以便我们可以应用VoiceOver定制。HStack本身接受其内容的闭包,这意味着我们不再可以依赖列表中的$0,因此我们将使用命名参数。

将当前列表替换为:

List(usedWords, id: \.self) { word in
    HStack {
        Image(systemName: "\(word.count).circle")
        Text(word)
    }
    .accessibilityElement(children: .ignore)
    .accessibility(label: Text("\(word), \(word.count) 个字母"))
}

如果您再次尝试游戏,您会看到它现在显示为“ spill,五个字母”,这要好得多。

优化 Bookworm 项目

项目11中,我们构建了Bookworm,这是一个应用程序,可让用户存储已阅读书籍的评分和描述,我们还引入了一个自定义的RatingView UI组件,该组件显示的星级为1到5。

再说一次,大多数应用程序在VoiceOver上都运行良好,但是评级控制是一个失败的尝试——它使用点击手势来添加功能,因此用户不会意识到它们是按钮,甚至无法传达它们是按钮的事实。应该代表评级。例如,如果我点击其中一个灰色的星标,VoiceOver会向我读出“星标,填充,图像,可能是飞机,星标”的信息——真的没有用。

这本身就是一个问题,但是这又是一个额外的问题,因为我们的RatingView设计为可重用的——这是您可以从该项目中获取的东西,并可以在其他十二个项目中使用,这仅意味着您最终污染了许多应用程序的可访问性。

我们可以使用三个修饰符来解决此问题,每个修饰符都添加到RatingView中当前的tapGesture()修饰符下方。首先,我们需要添加一个为每颗星星提供有意义的标签,如下所示:

.accessibility(label: Text("\(number == 1 ? "1 star" : "\(number) stars")"))

其次,我们可以删除.isImage特征,因为这些是图像并不重要:

.accessibility(removeTraits: .isImage)

最后,我们应该告诉系统每个星星实际上都是一个按钮,以便用户知道可以点击它。当我们在这里时,对于已经高亮的星星,则可以通过添加第二个特征.isSelected来使VoiceOver的工作做得更好。

因此,在最后两个下面添加最终修饰符:

.accessibility(addTraits: number > self.rating ? .isButton : [.isButton, .isSelected])

仅进行了三个小更改,但是此改进的组件比我们以前拥有的要好得多。

译自
Fixing Guess the Flag
Fixing Word Scramble
Fixing Bookworm

上一篇下一篇

猜你喜欢

热点阅读