voice over can only see a page of a uicollectionview

14,133

Solution 1

This answer worked for me, too. Thanks!

There is one other call you must have enabled to get this to work. Otherwise your method (void)accessibilityElementDidBecomeFocused will never get called. You must enable accessibility on the object Cell.

  1. Option 1: In ViewController, set the cell instance to have accessibility.

    Cell *cell = [cv dequeueReusableCellWithReuseIdentifier:kCellID forIndexPath:indexPath];
    [cell setIsAccessibilityElement:YES];
    
  2. Option 2: Implement the accessibility interface in the cell object:

    - (BOOL)isAccessibilityElement
    {
        return YES;
    }
    
    - (NSString *)accessibilityLabel {
        return self.label.text;
    }
    
    - (UIAccessibilityTraits)accessibilityTraits {
        return UIAccessibilityTraitStaticText;  // Or some other trait that fits better
    }
    
    - (void)accessibilityElementDidBecomeFocused
    {
        UICollectionView *collectionView = (UICollectionView *)self.superview;
        [collectionView scrollToItemAtIndexPath:[collectionView indexPathForCell:self] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally|UICollectionViewScrollPositionCenteredVertically animated:NO];
        UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self);
    }
    

Solution 2

After hours and hours of headache, the solution was really simple. If anyone else comes across a similar problem, this is what i did:

In the subclass of UICollectionViewCell that you are using for your CollectionView, override accessibilityElementDidBecomeFocused and implement it like this:

- (void)accessibilityElementDidBecomeFocused
{
    UICollectionView *collectionView = (UICollectionView *)self.superview;
    [collectionView scrollToItemAtIndexPath:[collectionView indexPathForCell:self] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally|UICollectionViewScrollPositionCenteredVertically animated:NO];
    UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}

Solution 3

Stephen's answer worked for me! Thanks.

I want to add that this seems to affect only iOS6; it looks like they fixed it in iOS7.

Also, you can make the scrolling slightly faster and cleaner by passing self instead of nil to UIAccessibilityPostNotification -- like so:

- (void)accessibilityElementDidBecomeFocused {    
    UICollectionView *collectionView = (UICollectionView *)self.superview;
    [collectionView scrollToItemAtIndexPath:[collectionView indexPathForCell:self] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally|UICollectionViewScrollPositionCenteredVertically animated:NO];
    UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, self);
}

Solution 4

This is how you would do it in Swift:

override func accessibilityElementDidBecomeFocused() {
    guard let collectionView = superview as? UICollectionView,
        let indexPath = collectionView.indexPath(for: self) else {
        return
    }

    collectionView.scrollToItem(at: indexPath, at: .left, animated: true)
    UIAccessibility.post(notification: .layoutChanged, argument: nil)
}
Share:
14,133
stephen
Author by

stephen

Updated on June 08, 2022

Comments

  • stephen
    stephen almost 2 years

    So i have a UICollectionView with a set of UICollectionViewCells displayed using a custom UILayout.

    I've configured the UILayout to lay out all the UICollectionViewCells almost exactly the same as how they are laid out in the photos app on ios.

    The problem is, it seems when voice over is turned on, and the user is traversing through the UICollectionViewCells using swipe, when the user gets to the last visible cell on the page, and tries to swipe forward to the next cell, it simply stops.

    I know that in UITableView the cells will just keep moving forward, and the table view will scroll down automatically.

    Does anyone know how to get this behaviour?

  • Nikhil Bhawsar
    Nikhil Bhawsar over 2 years
    thanks for sharing this answer, in my case I want not to have complete cell accessible but its contents, something similar - fileName and also moreOptions button, and with the above approach, I am not able to do the same. any workaround for this?
  • Ashis Laha
    Ashis Laha over 2 years
    I can think of alternative solution for your use-case @NikhilBhawsar. You need to use custom UILabel or UIButton instead of directly using them in the cell so that you can post accessibility notification (UIAccessibility.post(.layoutChange, argument: nil) when Label/Button is getting focused via accessibilityElementDidBecomeFocused() method.