译自 www.hackingwithswift.com/books/ios-s…
更多内容,欢迎关注公众号 「Swift花园」
喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀
在 SwiftUI 中支持特定的辅助功能需求
SwiftUI 提供了大量环境变量,描述了用户的自定义辅助设置,因此花点时间阅读和理解这些设置是值得的。
在项目 15 中,我们涉猎了标签、提示,控件特征,分组等辅助功能。但这里要介绍的辅助设置不一样,因为它们是通过环境提供的。这意味着 SwiftUI 会自动监控它们的变化,并在需要时自动调用我们的 body 属性。
例如,有一个辅助选项叫 “不以颜色区分”,它对于在人群中占比 1/12 的色盲群体是很有帮助的。但这项设置被启用时,应用会尝试借助形状,图标和纹理而不是颜色来让 UI 的含义更清晰。
添加这个环境属性来尝试:
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
这个属性是布尔型,你可以根据它的值来适配 UI。例如,下面的代码里我们为常规布局采用了一个简单的绿色背景,但当 “不以颜色区分” 启用时,我们采用黑色背景,外加一个复选标记:
struct ContentView: View {
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor
var body: some View {
HStack {
if differentiateWithoutColor {
Image(systemName: "checkmark.circle")
}
Text("成功")
}
.padding()
.background(differentiateWithoutColor ? Color.black : Color.green)
.foregroundColor(Color.white)
.clipShape(Capsule())
}
}
你可以在模拟器中打开设置应用,选择 辅助功能 > 显示和文子大小 > 不以颜色区分:
还有一个常见的选项是 “减弱动态效果”,位于 辅助功能 > 动态效果 > 减弱动态效果。当这项设置被启用时,应用会限制屏幕上会引起移动的动画数量。例如,iOS 应用的切换动画会由放大缩小变为淡入淡出。
在 SwiftUI 中,这意味着我们要对应地限制 withAnimation() 的使用,像下面这样:
struct ContentView: View {
@Environment(\.accessibilityReduceMotion) var reduceMotion
@State private var scale: CGFloat = 1
var body: some View {
Text("Hello, World!")
.scaleEffect(scale)
.onTapGesture {
if self.reduceMotion {
self.scale *= 1.5
} else {
withAnimation {
self.scale *= 1.5
}
}
}
}
}
不知道你是怎么想的,反正我觉得这么写着实恼人。好在我们可以借助对 withAnimation() 进行包装,在包装函数内部根据 UIKit’s UIAccessibility 来决定跳过动画还是执行动画:
func withOptionalAnimation<Result>(_ animation: Animation? = .default, _ body: () throws -> Result) rethrows -> Result {
if UIAccessibility.isReduceMotionEnabled {
return try body()
} else {
return try withAnimation(animation, body)
}
}
这样一来,当 “减弱动态效果” 启用时,闭包将立即执行,否则会传给 withAnimation()。这里的 throws/rethrows 是 Swift 的高级主题,是从 withAnimation() 的函数签名那里直接复制过来的,以便两个函数可以互相替换使用。
用法如下:
struct ContentView: View {
@State private var scale: CGFloat = 1
var body: some View {
Text("Hello, World!")
.scaleEffect(scale)
.onTapGesture {
withOptionalAnimation {
self.scale *= 1.5
}
}
}
}
通过这种方式,你就不再需要在各个地方都重复写动画的判断代码。
你应该考虑支持的选项还包括 “减弱透明度”。当这个设置启用时,应用应当减少模糊和透明设计的使用,以确保所有东西都足够清晰。
例如,下面的代码在 “减弱透明度” 启用时采用纯黑色背景,而不启用时则使用 50% 的透明度:
struct ContentView: View {
@Environment(\.accessibilityReduceTransparency) var reduceTransparency
var body: some View {
Text("Hello, World!")
.padding()
.background(reduceTransparency ? Color.black : Color.black.opacity(0.5))
.foregroundColor(Color.white)
.clipShape(Capsule())
}
}
接下来我们就要进入实际构建项目的过程了,请把工程还原回原始状态。
我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~