0

I’ve got a ViewController with a UICollectionView using an edge offset to lower its content on the screen, and a search bar that is added as a subview, whose frame has a negative y value so that it appears in the collection view above the content.

But as the search bar’s frame’s y value goes beyond a certain value (in this example, -45.0, but it depends on the size of the search bar), accessibility breaks: voice control will completely ignore it, and VoiceOver will ignore the search bar on the way down (it jumps directly from the ‘done’ button to the first collection view cell), although it will focus on the search bar on the way up.

If the frame's y > -45.0, accessibility functions as expected.

This isn’t caused by the search bar per se, as any UIView will cause the same issue

Is this a bug in UIAccessibility? Or is there something going on here that can explain this behaviour?

enter image description here

class ViewController: UIViewController {
    var myCollectionView: UICollectionView?
    var searchBar = UISearchBar()
    let searchBarHeight: CGFloat = 56
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let view = UIView()
        view.backgroundColor = .white
        setupCollectionView()
        addNavbar()
        addSearchBar()
        
    }
    
    func setupCollectionView() {
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 80, height: 80)
        
        myCollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        myCollectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
        myCollectionView?.backgroundColor = .red
        myCollectionView?.contentInset = UIEdgeInsets(top: 200,
                                                      left: 0,
                                                      bottom: 0,
                                                      right: 0)
        
        myCollectionView?.delegate = self
        myCollectionView?.dataSource = self
        
        view.addSubview(myCollectionView ?? UICollectionView())
        
        self.view = view
    }
    
    func addNavbar() {
        let navBar = UINavigationBar(frame: CGRect(x: 0, y: 44, width: view.frame.size.width, height: 44))
        view.addSubview(navBar)

        let navItem = UINavigationItem()
        let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
        navItem.rightBarButtonItem = doneItem

        navBar.setItems([navItem], animated: false)
    }
    
    func addSearchBar() {
        searchBar.backgroundColor = .brown
        searchBar.frame = CGRect(x: 0,
                                 y: -searchBarHeight * 2,
                                 width: view.frame.width,
                                 height: searchBarHeight)
        myCollectionView?.addSubview(searchBar)
    }

}

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 8
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath)
        cell.backgroundColor = .cyan
        cell.isAccessibilityElement = true
        cell.accessibilityLabel = "cell \(indexPath.row)"
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let cell = collectionView.cellForItem(at: indexPath)
        cell?.backgroundColor = .darkGray
    }
}

c_booth
  • 2,185
  • 1
  • 13
  • 22

0 Answers0