【问题标题】:Accessibility focus order not working as expected [iOS]辅助功能焦点顺序未按预期工作 [iOS]
【发布时间】:2021-01-16 03:28:54
【问题描述】:

概览 我无法获得正确的焦点顺序(iOS 中的辅助功能)。似乎 becomeFirstResponder() 覆盖了我在数组中指定的焦点顺序,并导致 Voice Over Accessibility 功能首先读取错误的 Accessibility Label。

详情: 我有一个带有 containerView 的视图控制器。在里面我有我的进度条图像和文本输入字段(占位符)的 UIView。这两个元素都有 isAccessibilityElement = true 属性,并且它们已添加到我的焦点顺序数组中。但是在屏幕启动时,焦点顺序转到输入字段而不是进度条 UIView。

经过扩展测试,我注意到如果我删除下面的代码行,这个问题将不再可复制。

 otpNumberTextField.becomeFirstResponder()

但这不是解决方案。我需要文本字段中的光标,但需要语音功能来首先阅读我的进度条辅助功能标签。如何解决?

特定场景 我注意到这个问题只有在我有一个最后一个活动焦点在文本字段上的 VC,然后转换到下一个 VC(带有一个文本字段和一个进度条)时才会出现。

当我的 VC 将最后一个活动焦点放在按钮上,然后转换到下一个 VC(带有文本字段和进度条)时,错误是不可复制的。

代码片段

import UIKit

class MyViewController: UIViewController, UITextFieldDelegate {

    var otpNumberTextField = UITextField()
    var progressMainDot = UIImageView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        
        setupView()
        setupBinding()
    }

    override func viewWillAppear(_ animated: Bool) {
        setupView()
        textFieldDidChange(otpNumberTextField)
    }
    
    func setupView(){
        let containerView = UIView()
        containerView.backgroundColor = UIColor.init(named: ColourUtility.BackgroundColour)
        view.addSubview(containerView)
        containerView.translatesAutoresizingMaskIntoConstraints = false
        containerView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
        containerView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
        containerView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        containerView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        
        //Progress Bar
        let progressBarView = UIView()
        containerView.addSubview(progressBarView)
        progressBarView.isAccessibilityElement = true
        progressBarView.accessibilityLabel = "my accessibility label"
        progressBarView.translatesAutoresizingMaskIntoConstraints = false
        
        progressMainDot.image = UIImage(named:ImageUtility.progressMain)
        progressMainDot.contentMode = .scaleAspectFit
        progressBarView.addSubview(progressMainDot)
        
        //Text Field
        otpNumberTextField.borderStyle = UITextField.BorderStyle.none
        otpNumberTextField.font = UIFontMetrics.default.scaledFont(for: FontUtility.inputLargeTextFieldStyle)
        otpNumberTextField.adjustsFontForContentSizeCategory = true
        otpNumberTextField.isAccessibilityElement = true
        otpNumberTextField.accessibilityLabel = AccessibilityUtility.enterVerificationCode
        otpNumberTextField.placeholder = StringUtility.otpPlaceholder
        otpNumberTextField.textColor = UIColor.init(named: ColourUtility.TextfieldColour)
        otpNumberTextField.textAlignment = .center
        otpNumberTextField.keyboardType = .numberPad
        otpNumberTextField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
        containerView.addSubview(otpNumberTextField)
        otpNumberTextField.becomeFirstResponder()
        
        //Accessibility - focus order
        view.accessibilityElements = [progressBarView, otpNumberTextField]
    }
      
    //... more code goes here ...

}

【问题讨论】:

    标签: ios swift accessibility voiceover becomefirstresponder


    【解决方案1】:

    如果您已经设置了accessibilityElements,那么画外音应该遵守该顺序,但调用becomeFirstResponder() 会将焦点更改为该文本字段。

    您可以尝试下面的代码,该代码会通知语音由于布局更改而将焦点转移到新元素。

    UIAccessibility.post(notification: .layoutChanged, argument: progressBarView)
    

    所以现在你修改的方法应该如下:

    func setupView(){
        .....
        otpNumberTextField.becomeFirstResponder()
    
        //Accessibility - focus order
        view.accessibilityElements = [progressBarView, otpNumberTextField]
                
        UIAccessibility.post(notification: .layoutChanged, argument: progressBarView)
    
        .....
    }
    

    【讨论】:

    • Om Prakash 我以前试过这个,但解决方案似乎有问题。当我使用下面的代码时,VoiceOver 仍然首先开始读取 InputTextfield,并且只有在一段时间后它才会切换并开始读取我的进度条。我目前实施了一种解决方法,以通过“otpNumberTextField.accessibilityElementsHidden = true”从语音中隐藏 TextField,然后在 5 秒后使用函数取消隐藏它。这样,VoiceOver 首先开始阅读进度条。另请注意,仅当先前的 VC 聚焦于另一个输入字段时才会出现此错误(对于最后一个活动焦点位于按钮上的 VC 不会发生)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 2020-04-28
    • 2021-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多