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?
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
}
}