如何使任意 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 读取辅助功能值(01),因为 "Off" 或 "On," 添加提示 "Double tap to toggle setting",并使 VoiceOver 说 "Switch Button."

您可以像这样通过覆盖视图的辅助功能特性来做到这一点:

override var accessibilityTraits(): UIAccessibilityTraits {
    get { return UISwitch().accessibilityTraits }
    set {}
}

希望对您有所帮助!