辅助功能焦点订单无法正常运行[iOS]

问题描述

概述 我在获取正确的焦点顺序(iOS中的辅助功能)时遇到麻烦。似乎beginFirstResponder()会覆盖我在数组中指定的焦点顺序,并导致Voice Over Accessibility功能首先读取错误的Accessibility Label。

详细信息: 我有一个带有containerView的View Controller。在内部,我有进度条图像和文本输入字段(占位符)的UIView。这两个元素都具有 isAccessibilityElement = true 属性,它们已添加到我的焦点顺序数组中。但是,在屏幕启动时,焦点顺序转到输入字段,而不是进度条UIView。

经过扩展测试后,我发现如果删除下面的代码行,则此问题不再可复制。

 otpNumberTextField.becomeFirstResponder()

但这不是解决方案。我需要在文本字段中使用光标,但需要使用Voice Over功能才能先阅读进度栏可访问性标签。如何解决

特定场景 我已经注意到,只有当我的VC最后一次活跃在Textfield上,然后过渡到下一个VC(带有Textfield和Progress Bar)时,才会出现此问题。

当我拥有VC,并且最后一次将焦点集中在Button上,然后过渡到下一个VC(具有Textfield和Progress Bar)时,错误不可复制。

代码片段

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 ...

}

解决方法

如果您已经设置了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)

    .....
}