Saturday 3 October 2020

Accessibility focus order not working as expected [iOS]

OVERVIEW I'm having trouble getting correct focus order (Accessibility in iOS). It seems like becomeFirstResponder() overwrites my focus order I have specified in the array and causes Voice Over Accessibility functionality to read wrong Accessibility Label first.

DETAILS: I have a View Controller with containerView. Inside I have UIView of my progress bar image and text input field (placeholder). Both elements have isAccessibilityElement = true attributes and they have been added to my focus order array. However upon screen launch, focus order goes to the input field instead of progress bar UIView.

After extended testing I've noticed that this issue is no longer replicable if I remove below line of code.

 otpNumberTextField.becomeFirstResponder()

But this is not a solution. I need cursor in the textfield but Voice Over functionality to read my Progress Bar Accessibility Label first. How to fix it?

CODE SNIPPET

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

}


from Accessibility focus order not working as expected [iOS]

No comments:

Post a Comment