如何在MacOS上为VoiceOver实现NSSlider Accessible?

时间:2018-04-15 12:39:34

标签: swift macos accessibility voiceover

我有一个滑块:NSSlider和valueLabel:NSTextField,我想知道什么是让VoiceOver用户可以访问它的正确方法。

首先我将slider的发送动作连接到sliderChanged函数以更新valueLabel。

valueLabel.stringValue = String(slider.integerValue)

VoiceOver正确读取标签,但它以百分比形式读取滑块。为了解决这个问题,我将sliderChanged函数更改为setAccessibilityValueDescription。

slider.setAccessibilityValueDescription(String(slider.integerValue))

现在,VoiceOver正确读取滑块的值。但是,它同时看到了valueLabel和slider,因此它是多余的。

我尝试了valueLabel.setAccessibilityElement(false),但VoiceOver似乎没有忽略。

有人可以告知实施这个的正确方法是什么?谢谢!

1 个答案:

答案 0 :(得分:1)

执行此操作的最佳方法是创建包含标签和滑块的自定义“ContainerView”类(继承自UIView),使ContainerView成为accessibilityElement,并将其accessibilityTraits设置为“可调整”。通过创建同时包含valueLabel和滑块的ContainerView,可以删除当前实现中存在的冗余,同时不会影响非VoiceOver用户的slider / valueLabel的布局或可用性。此答案基于this video,因此,如果某些内容不清楚或您想要更深入的信息,请观看视频!

将视图的UIAccessibilityTraits设置为“Adjustable”允许您使用其功能accessibilityIncrement和accessibilityDecrement,以便您可以更新所需的任何内容(滑块,文本字段等)。此特征允许任何视图像典型的可调整(无需添加UIGestureRecognizers或其他VoiceOver公告)。

为方便起见,我在下面发布了我的代码,但它主要基于我上面链接的视频。 (我个人是iOS开发人员,所以我的Swift代码是基于iOS的)

注意 - 我必须覆盖“accessibilityValue”变量 - 这是为了让VoiceOver在用户向上或向下滑动时宣布滑块中的更改。

我的ContainerView类包含以下代码:

class ContainerView: UIView {

    static let LABEL_TAG = 1
    static let SLIDER_TAG = 2

    var valueLabel: UILabel {
        return self.viewWithTag(ContainerView.LABEL_TAG) as! UILabel
    }

    var slider: UISlider {
        return self.viewWithTag(ContainerView.SLIDER_TAG) as! UISlider
    }

    override var accessibilityValue: String? {
        get { return valueLabel.text }
        set {}
    }

    override var isAccessibilityElement: Bool {
        get { return true }
        set { }
    }

    override var accessibilityTraits: UIAccessibilityTraits {
        get { return UIAccessibilityTraitAdjustable }
        set { }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        valueUpdated()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        valueUpdated()
    }

    func valueUpdated() {
        valueLabel.text = String(slider.value)
        slider.sendActions(for: .valueChanged)
    }

    override func accessibilityIncrement() {
        super.accessibilityIncrement()

        slider.setValue(slider.value + 1, animated: true)
        valueUpdated()
    }

    override func accessibilityDecrement() {
        super.accessibilityDecrement()

        slider.setValue(slider.value - 1, animated: true)
        valueUpdated()
    }
}

希望这有帮助!