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

Posted

技术标签:

【中文标题】如何使任意 UIAccessibilityElement 的行为类似于 VoiceOver 的 UISwitch?【英文标题】:How can I make an arbitrary UIAccessibilityElement behave like a UISwitch for VoiceOver? 【发布时间】:2018-09-07 23:22:54 【问题描述】:

当使用VICEOVER选择本机交换机时,该公告将包含“关闭”或“ON”,其中附加提示“双击以切换设置”。

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

使用辅助功能检查器时,我还注意到原生 UIKit 开关在启用时的辅助功能值为 1,但前提是不会改变 VoiceOver 的行为。

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


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

是否可以提供一些特征/值/标签的组合,以便 TalkBack 将此元素识别为 Switch,而不使用 UISwitch?

【问题讨论】:

【参考方案1】:

我创建了一个可访问的视图,其作用类似于开关here。

我能够让任意元素像 Switch 一样工作的唯一方法是继承 Switch 的 UIAccessibilityTraits。这会导致 VoiceOver 将辅助功能值(01)读取为“关闭”或“打开”,并添加“双击切换设置”提示,并让 VoiceOver 说出“切换按钮”。

您可以通过覆盖视图的 Accessibility Traits 来实现这一点,如下所示:

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

希望这会有所帮助!

【讨论】:

您可以通过继承 UISwitch 来实现类似的行为,而无需创建空的开关对象。【参考方案2】:

您可以根据需要创建一个自定义的可访问性元素,其行为类似于 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)


最后,要让自定义视图表现得像一个开关控件,只需在你的 WrapView 类中重写 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。

【讨论】:

下面的答案要好得多。这个答案很脆弱,并没有捕捉到 UISwitch 的所有行为。只是那些显而易见的。 你是对的@ChrisCM,它肯定要好得多,因为它包含了许多行为。 ? 我提供的代码的目的很简单,就是展示如何处理一个简单而具体的示例,以了解基础知识:当同化时,下一步肯定是 jldailey,我同意。 ? 非常好的响应 XLE_22。当接受的答案不如其他人时,我会感到紧张。那些乐于指出别人答案价值的人太棒了!

以上是关于如何使任意 UIAccessibilityElement 的行为类似于 VoiceOver 的 UISwitch?的主要内容,如果未能解决你的问题,请参考以下文章

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

如何使 python 命令行程序自动完成任意事物而不是解释器

如何使 Excel 在 MS SQL 2017 中任意旋转(交叉连接 + 循环)

thinkphp如何使volist中的编号$i从任意数开始

如何使用点击事件使其不会传播到视图

JS教你如何在对象内任意位置插入任意属性