swift - 如何在 MacOS 上实现 VoiceOver 可访问的 NSSlider?

标签 swift macos accessibility voiceover

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

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

valueLabel.stringValue = String(slider.integerValue)

VoiceOver 正确读取标签,但它读取 slider 的百分比。为解决此问题,我将 sliderChanged 函数更改为 setAccessibilityValueDescription。

slider.setAccessibilityValueDescription(String(slider.integerValue))

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

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

有人可以建议什么是实现这个的正确方法吗?谢谢!

最佳答案

执行此操作的最佳方法是创建一个包含标签和 slider 的自定义“ContainerView”类(继承自 UIView),使 ContainerView 成为 accessibilityElement,并将其 accessibilityTraits 设置为“adjustable”。通过创建一个包含 valueLabel 和 slider 的 ContainerView,您可以删除当前实现中存在的冗余,同时不会影响非 VoiceOver 用户的 slider /valueLabel 的布局或可用性。此答案基于 this video ,所以如果有什么不明白的地方或者您想了解更深入的信息,请观看视频!

将 View 的 UIAccessibilityTraits 设置为“可调整”允许您使用其函数 accessibilityIncrement 和 accessibilityDecrement,以便您可以更新任何您需要的内容( slider 、文本字段等)。此特性允许任何 View 像典型的可调整 View 一样运行(无需添加 UIGestureRecognizers 或额外的 VoiceOver 通知)。

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

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

我的 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()
    }
}

希望这对您有所帮助!

关于swift - 如何在 MacOS 上实现 VoiceOver 可访问的 NSSlider?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49842006/

相关文章:

ios - 带有底层背景图像的可缩放 PKCanvasView

c++ - 在 Objective-C++ 的 .h 文件中添加指向定义的 Objective-C 类的指针

macos - 使用 NSArrayController 时得到 "valueForUndefinedKey: this class is not key value coding-compliant for the key error"

html - 制作 HTML 表单元素 'display only' - 非交互式

ios - Xcode Instrument 中 SCNNodes 上 SCNAudioPlayer 的持久化

swift - 正确使用 facebook app-scoped user id

swift - 使用 Swift 3 按下时动画单元格

python - 在 OS X 后台运行 Python

iphone - 如何防止 VoiceOver 光标在布局更改时重置其位置

ios - UiCollectionView 辅助功能焦点