如何使任意 UIAccessibilityElement 的行为类似于 VoiceOver 的 UISwitch?
How can I make an arbitrary UIAccessibilityElement behave like a UISwitch for VoiceOver?
使用 VoiceOver 选择本机开关时,公告将包含 "Off" 或 "On" 以及附加提示 "double tap to toggle setting"。
我已经尝试使用可访问性特征 UIAccessibilityTraitSelected
,但这只会导致 "Selected" 被宣布,没有任何提示,除非我明确提供。
使用 Accessibility Inspector 我还注意到原生 UIKit 开关在启用时具有 1
的 accessibilityValue,但前提是不会改变 VoiceOver 行为。
- (UIAccessibilityTraits)accessibilityTraits {
if (toggled) {
return UIAccessibilityTraitSelected;
} else {
return UIAccessibilityTraitNone;
}
}
- (NSString*)accessibilityValue {
if (toggled) {
return @"1";
} else {
return @"0"
}
}
是否可以提供 traits/value/label 的某种组合,以便 TalkBack 将此元素识别为 Switch,而无需使用 UISwitch?
您可以随心所欲地创建一个行为类似于 UISwitchControl 的自定义辅助功能元素。
唯一需要指定的是 VoiceOver 解释它的方式。
假设您想要收集一个 label
和一个 view
来作为开关控件。
首先,创建一个 class 用于将这些元素 组合成一个:
class WrapView: UIView {
static let defaultValue = "on"
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(with label: UILabel,and view: UIView) {
let viewFrame = label.frame.union(view.frame)
self.init(frame: viewFrame)
self.isAccessibilityElement = true
self.accessibilityLabel = label.accessibilityLabel
self.accessibilityValue = WrapView.defaultValue
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
}
}
然后,只需 在 viewDidAppear()
中创建您的自定义视图 :
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
@IBOutlet weak var myLabel: UILabel!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let myCustomView = WrapView.init(with: myLabel, and: myView)
self.view.addSubview(myCustomView)
}
}
最后,要让自定义视图像开关控件一样工作,只需重写 WrapView
class 中的 accessibilityActivate
函数即可在双击视图时实现您的逻辑:
override func accessibilityActivate() -> Bool {
self.accessibilityValue = (self.accessibilityValue == WrapView.defaultValue) ? "off" : "on"
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
return true
}
现在您有一个自定义元素,其中包含您想要的任何内容,并且它的行为类似于使用 VoiceOver 的盲人的开关控件,而无需根据需要使用 UISwitch。
我创建了一个像开关一样的可访问视图 here。
我能够让任意元素像 Switch 一样工作的唯一方法是继承 Switch 的 UIAccessibilityTraits。这会导致 VoiceOver 读取辅助功能值(0
或 1
),因为 "Off" 或 "On," 添加提示 "Double tap to toggle setting",并使 VoiceOver 说 "Switch Button."
您可以像这样通过覆盖视图的辅助功能特性来做到这一点:
override var accessibilityTraits(): UIAccessibilityTraits {
get { return UISwitch().accessibilityTraits }
set {}
}
希望对您有所帮助!
使用 VoiceOver 选择本机开关时,公告将包含 "Off" 或 "On" 以及附加提示 "double tap to toggle setting"。
我已经尝试使用可访问性特征 UIAccessibilityTraitSelected
,但这只会导致 "Selected" 被宣布,没有任何提示,除非我明确提供。
使用 Accessibility Inspector 我还注意到原生 UIKit 开关在启用时具有 1
的 accessibilityValue,但前提是不会改变 VoiceOver 行为。
- (UIAccessibilityTraits)accessibilityTraits {
if (toggled) {
return UIAccessibilityTraitSelected;
} else {
return UIAccessibilityTraitNone;
}
}
- (NSString*)accessibilityValue {
if (toggled) {
return @"1";
} else {
return @"0"
}
}
是否可以提供 traits/value/label 的某种组合,以便 TalkBack 将此元素识别为 Switch,而无需使用 UISwitch?
您可以随心所欲地创建一个行为类似于 UISwitchControl 的自定义辅助功能元素。 唯一需要指定的是 VoiceOver 解释它的方式。
假设您想要收集一个 label
和一个 view
来作为开关控件。
首先,创建一个 class 用于将这些元素 组合成一个:
class WrapView: UIView {
static let defaultValue = "on"
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(with label: UILabel,and view: UIView) {
let viewFrame = label.frame.union(view.frame)
self.init(frame: viewFrame)
self.isAccessibilityElement = true
self.accessibilityLabel = label.accessibilityLabel
self.accessibilityValue = WrapView.defaultValue
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
}
}
然后,只需 在 viewDidAppear()
中创建您的自定义视图 :
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
@IBOutlet weak var myLabel: UILabel!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let myCustomView = WrapView.init(with: myLabel, and: myView)
self.view.addSubview(myCustomView)
}
}
最后,要让自定义视图像开关控件一样工作,只需重写 WrapView
class 中的 accessibilityActivate
函数即可在双击视图时实现您的逻辑:
override func accessibilityActivate() -> Bool {
self.accessibilityValue = (self.accessibilityValue == WrapView.defaultValue) ? "off" : "on"
self.accessibilityHint = "element is" + self.accessibilityValue! + ", tap twice to change the status."
return true
}
现在您有一个自定义元素,其中包含您想要的任何内容,并且它的行为类似于使用 VoiceOver 的盲人的开关控件,而无需根据需要使用 UISwitch。
我创建了一个像开关一样的可访问视图 here。
我能够让任意元素像 Switch 一样工作的唯一方法是继承 Switch 的 UIAccessibilityTraits。这会导致 VoiceOver 读取辅助功能值(0
或 1
),因为 "Off" 或 "On," 添加提示 "Double tap to toggle setting",并使 VoiceOver 说 "Switch Button."
您可以像这样通过覆盖视图的辅助功能特性来做到这一点:
override var accessibilityTraits(): UIAccessibilityTraits {
get { return UISwitch().accessibilityTraits }
set {}
}
希望对您有所帮助!