如何使任意UIAccessibilityElement的行为类似于VoiceOver的UISwitch?

时间:2018-09-07 23:22:54

标签: ios accessibility voiceover

使用VoiceOver选择本机开关时,公告将包含“关”或“开”,并带有附加提示“双击切换设置”。

我尝试使用可访问性特征UIAccessibilityTraitSelected,但这只会导致宣布“已选择”,除非我明确提供,否则没有任何提示。

使用可访问性检查器,我还注意到,当启用时,本机UIKit开关的accessibilityValue值为1,但提供该设置不会改变VoiceOver的行为。

- (UIAccessibilityTraits)accessibilityTraits {
  if (toggled) {
    return UIAccessibilityTraitSelected;
  } else {
    return UIAccessibilityTraitNone;
  }
}

- (NSString*)accessibilityValue {
  if (toggled) {
    return @"1";
  } else {
    return @"0"
  }
}

是否可以提供特征/值/标签的某种组合,以使TalkBack无需使用UISwitch即可将此元素识别为Switch?

2 个答案:

答案 0 :(得分:4)

我已经创建了一个类似于开关here的可访问视图。

我能够获取任意元素以使其像Switch一样的唯一方法是在继承Switch的UIAccessibilityTraits时。这将使VoiceOver读取“无障碍”值(01)为“关”或“开”,添加提示“双击切换设置”,并使VoiceOver说“切换按钮”。

您可以通过如下方式覆盖视图的辅助功能来实现此目的:

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

希望这会有所帮助!

答案 1 :(得分:1)

您可以使用任何所需的内容创建自定义可访问性元素,就像UISwitchControl一样。 唯一要指定的是VoiceOver解释它的方式。

让我们假设您想收集一个label和一个view作为开关控件。

首先,创建一个将这些元素分组为单个元素的类

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)
}
}

最后,要拥有一个像开关控件一样的自定义视图,只需在两次点击视图时覆盖accessibilityActivate类中的WrapView函数即可实现逻辑:

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的盲人来说,其行为就像一个开关控件。