2

So I have a UICollectionView in a UIViewController which is one of the root view controllers in the tab bar. I set a contentInset for the UICollectionView so I can Add a Label to the top of the collectionView, at which point it would mean that the UILabel is part of the collectionView but is not part of the headerView of the collectionView. To achieve the addition of the UILabel to the UICollectionView, I use

collectionView.addSubview(theLabel)

and I turn voice over on and run the application. what happens is that the voiceover goes through all the UICollectionViewCells in the correct order all the way to the last CollectionViewCell to begin, then goes to the Label which is at the top of the collectionView and then goes to the tabBar. I tried the answer in this Change order of read items with VoiceOver, but had no luck, this solution did change the order of

self.accessibilityElements

to the way I want, except the voice over doesn't really follow the order in self.accsibilityElements and I am not really sure what is going on, has anyone come across the same trouble with the accessibility order being screwed up because "addsubView" was used on the UICollectionView. IF (and I say IF, because I don't think anyone would have added a subView to a collectionView this way) anyone has any thoughts please help me out here, been stuck with this bug the longest time.

Edit

class CollectionViewSubViewsAddedByTags: UICollectionView {

override func awakeFromNib() {
    super.awakeFromNib()
}

var accessibilityElementsArray = [AnyObject]()

override var accessibilityElements: [AnyObject]?{

    get{
        return accessibilityElementsArray
    }

    set(newValue) {
        super.accessibilityElements = newValue
    }
}

override func accessibilityElementCount() -> Int {
    return accessibilityElementsArray.count
}

override func accessibilityElementAtIndex(index: Int) -> AnyObject? {
    return self.accessibilityElementsArray[index]
}

override func indexOfAccessibilityElement(element: AnyObject) -> Int {
    return (accessibilityElementsArray.indexOf({ (element) -> Bool in
        return true
    }))!
}

override func didAddSubview(subview: UIView) {
    super.didAddSubview(subview)
    accessibilityElementsArray.append(subview)
    accessibilityElementsArray.sortInPlace { $0.tag<($1.tag)}
}

override func willRemoveSubview(subview: UIView) {
    super.willRemoveSubview(subview)
    if let index = (accessibilityElementsArray.indexOf({ (element) -> Bool in
        return true
    })) {
        accessibilityElementsArray.removeAtIndex(index)
    }

}

}

Thanks, Shabri

Community
  • 1
  • 1
Shabarinath Pabba
  • 1,359
  • 2
  • 13
  • 22
  • why would u want to add a subview to collection view ? – Teja Nandamuri Nov 12 '15 at 14:55
  • we could have gone with 1 of these 2 solutions, we already have another view(lets call this view advertisementView) inside the header 1) add theLabel in with the advertisementView inside the header for the collectionView 2) Add theLabel to the top of the cpollectionView by giving the collectionView a contentInset. if we go by the first approach, the issue comes when we are in landscape we don't want to see the label, lets say I add theLabel and the advertisementView to the headerView with some constants, when I hide theLabel in landscape, I would have issues with the constraints – Shabarinath Pabba Nov 12 '15 at 20:33
  • at the same time I hide the navigation bar when we are at the top of the collectionView, I also want to keep tag of how much a user has scrolled, because once the user has scrolled after the label, I unhide the navigation Bar – Shabarinath Pabba Nov 12 '15 at 20:38
  • show the code of what u tried to change the accessibility order – Teja Nandamuri Nov 13 '15 at 13:42
  • @Mr.T I just added the code, check "didAddSubView" – Shabarinath Pabba Nov 16 '15 at 16:12
  • @Mr.T any suggestions? – Shabarinath Pabba Nov 30 '15 at 17:11
  • if you want to reorder the accessibility elements, you need to moidiufy the array accessibilityElements – Teja Nandamuri Nov 30 '15 at 17:23
  • yes but in the getter and setter, I set accessibilityElementsArray to "accesibilityElements" – Shabarinath Pabba Nov 30 '15 at 17:51

1 Answers1

1

I've run into the same issue - I'm using a top inset on our UICollectionView to allow room for a header that slides on/off screen with scroll. If I use Voice Over with this layout then the entire system gets confused and the focus order is incorrect. What I've done to get around this is use an alternate layout when VO is activated - instead of placing the header over the collection view with an inset, I place the header vertically above the collection view and set 0 top inset on the collection view.

tyler
  • 2,865
  • 1
  • 23
  • 28