如何让 iOS VoiceOver 在文本元素(不是当前焦点)发生变化时读取它?
How to make iOS VoiceOver read a Text element (not current focus) when it changes?
我正在尝试制作一个模拟 Apple 计算器应用程序行为的应用程序。在计算器上,当您点击 =(等于)时,应用程序会从主显示视图中读取“结果,数字。”。如何在 SwiftUI 中重现此行为?
我的测试场景:
struct ContentView: View {
@State var result = 0
var body: some View {
VStack {
Text("\(result)")
.font(.largeTitle)
.frame(height: 100)
.padding()
Spacer()
Button(action: {
self.result += 1
}, label: {
Text("Add one")
.font(.title)
.padding()
})
Button(action: {
self.result -= 1
}, label: {
Text("Minus one")
.font(.title)
.padding()
})
}
}
}
我希望每次结果发生变化时,通过添加或减号按钮的交互,VoiceOver 系统检测到结果变化并读取结果。
您可以post Voice over 的通知来宣布一些事情。但是我不熟悉 SwiftUI,所以不确定在你的例子中最好把这段代码放在哪里
post通知的代码是:
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: .announcement, argument: "message to announce")
}
也许你可以这样做:
function announceResult() {
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: .announcement, argument: self.result)
}
}
Button(action: {
self.result += 1
announceResult()
}
您只需在视图主体上使用 accessibility(value:)
修饰符即可。
var body: some View {
VStack {
Text("\(result)")
.font(.largeTitle)
.frame(height: 100)
.padding()
Spacer()
Button(action: {
self.result += 1
}, label: {
Text("Add one")
.font(.title)
.padding()
})
Button(action: {
self.result -= 1
}, label: {
Text("Minus one")
.font(.title)
.padding()
})
}
.accessibility(value: Text("\(result)"))
}
这是我的最终解决方案:
struct ContentView: View {
@State var result = 0 {
didSet {
announce(this: "\(result)")
}
}
var body: some View {
VStack {
Text("\(result)")
.font(.largeTitle)
.frame(height: 100)
.padding()
Spacer()
Button(action: {
self.result += 1
}, label: {
Text("Add one")
.font(.title)
.padding()
})
Button(action: {
self.result -= 1
}, label: {
Text("Minus one")
.font(.title)
.padding()
})
}
//.accessibility(value: Text("\(result)"))
}
private func announce(this: String) {
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: .screenChanged, argument: "The new result is \(this).")
}
}
}
我正在寻找的通知是 .screenChanged,但我也想使用 @Scriptable 提到的 .announcement。
有时您必须使用 DispatchQueue.main.asyncAfter 来解决竞争条件,如在:
中提到的
在这里我找到了其他通知:Default UIAccessibilityElement after screen change
我正在尝试制作一个模拟 Apple 计算器应用程序行为的应用程序。在计算器上,当您点击 =(等于)时,应用程序会从主显示视图中读取“结果,数字。”。如何在 SwiftUI 中重现此行为?
我的测试场景:
struct ContentView: View {
@State var result = 0
var body: some View {
VStack {
Text("\(result)")
.font(.largeTitle)
.frame(height: 100)
.padding()
Spacer()
Button(action: {
self.result += 1
}, label: {
Text("Add one")
.font(.title)
.padding()
})
Button(action: {
self.result -= 1
}, label: {
Text("Minus one")
.font(.title)
.padding()
})
}
}
}
我希望每次结果发生变化时,通过添加或减号按钮的交互,VoiceOver 系统检测到结果变化并读取结果。
您可以post Voice over 的通知来宣布一些事情。但是我不熟悉 SwiftUI,所以不确定在你的例子中最好把这段代码放在哪里
post通知的代码是:
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: .announcement, argument: "message to announce")
}
也许你可以这样做:
function announceResult() {
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: .announcement, argument: self.result)
}
}
Button(action: {
self.result += 1
announceResult()
}
您只需在视图主体上使用 accessibility(value:)
修饰符即可。
var body: some View {
VStack {
Text("\(result)")
.font(.largeTitle)
.frame(height: 100)
.padding()
Spacer()
Button(action: {
self.result += 1
}, label: {
Text("Add one")
.font(.title)
.padding()
})
Button(action: {
self.result -= 1
}, label: {
Text("Minus one")
.font(.title)
.padding()
})
}
.accessibility(value: Text("\(result)"))
}
这是我的最终解决方案:
struct ContentView: View {
@State var result = 0 {
didSet {
announce(this: "\(result)")
}
}
var body: some View {
VStack {
Text("\(result)")
.font(.largeTitle)
.frame(height: 100)
.padding()
Spacer()
Button(action: {
self.result += 1
}, label: {
Text("Add one")
.font(.title)
.padding()
})
Button(action: {
self.result -= 1
}, label: {
Text("Minus one")
.font(.title)
.padding()
})
}
//.accessibility(value: Text("\(result)"))
}
private func announce(this: String) {
if UIAccessibility.isVoiceOverRunning {
UIAccessibility.post(notification: .screenChanged, argument: "The new result is \(this).")
}
}
}
我正在寻找的通知是 .screenChanged,但我也想使用 @Scriptable 提到的 .announcement。
有时您必须使用 DispatchQueue.main.asyncAfter 来解决竞争条件,如在:
在这里我找到了其他通知:Default UIAccessibilityElement after screen change