Search code examples
iosswiftuiaccessibility

Not getting right coordinates for UIAccessibilityElement


I'm trying to do grouping of my button with my label but not getting the rectangle for accessibility at right place.

After swiping all the way to get to the element, it takes right width and height but y-position is completely wrong. It speaks the right VO but I don't know why position is incorrect. I have following code,

let checkboxAccessible = UIAccessibilityElement(accessibilityContainer: view)
let unionRect = passwordCheckbox.frame.union(showPasswordText.frame)
checkboxAccessible.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(unionRect, self.view)
checkboxAccessible.accessibilityLabel = NSLocalizedString("Show Password", comment: "showPasswordText")
view.accessibilityElements = [productTitle, leadInText, emailTextField, passwordTextField, checkboxAccessible, loginButton, forgotPasswordView, helpButton]

Any help will be appreciated.


Solution

  • I had the same issue where I was having a StackView which had two IBOutlets (Let's say a title and a value). And I had been struggling for months and couldn't figure out why my container couldn't find the correct position of the frame (self.frame).

    Recently when I came back trying to solve this, I saw the Apple documenation that they were using union() function. I tried it out in my case and it worked perfectly!

    Example of working grouped elements:

    class CustomView: UIView {
        @IBOutlet weak var titleLabel: UILabel!
        @IBOutlet weak var valueLabel: UILabel!
        
        private var _accessibilityElements: [Any]?
        override var accessibilityElements: [Any]? {
            set {
                _accessibilityElements = newValue
            }
            
            get {
                guard _accessibilityElements == nil else {
                    return _accessibilityElements
                }
                
                var elements = [UIAccessibilityElement]()
                
                guard let titleText = titleLabel.text,
                    let valueText = valueLabel.text else {
                        return elements
                }
                
                let latitudeElement = UIAccessibilityElement(accessibilityContainer: self)
                latitudeElement.accessibilityLabel = "\(titleText), \(valueText)"
                latitudeElement.accessibilityFrameInContainerSpace = titleLabel.frame.union(valueLabel.frame) // Before: "self.frame"
                elements.append(latitudeElement)
                _accessibilityElements = elements
                
                return _accessibilityElements
            }
        }
        
        func removeAccessibilityElements() {
            _accessibilityElements = nil
        }
    }