Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 8.4: Scroll view resets contentOffset with Voice Over enabled shortly after view appear

With Voice Over enabled scroll views reset their preset contentOffset a second after view did appear. It happens on iOS 8.4 devices, no reproduction for 9.0. Looks some internal UIScrollViewAccessibility code forces scroll view to setContent: for zero when becoming focused. Didn't find any way to evade this.

Any thoughts?

Related code sample illustrates the bug. Just create a view with collection view, create a cell with reuse id "Cell" and put a label on it.

@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
@property (nonatomic, weak) IBOutlet UICollectionView *collectionView;
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.collectionView.backgroundColor = [UIColor clearColor];
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.collectionView reloadData];
    //set there 4 seconds and bug will disappear
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:5 inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
    });
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    NSLog(@"Why you scroll second time?");
}
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return self.view.bounds.size;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 10;
}
- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
    UILabel *label = (UILabel*)cell.contentView.subviews[0];
    label.text = @(indexPath.item + 1).stringValue;
    if (indexPath.item == 5) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{           UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, label);
        });
    }
    return cell;
}
@end
like image 279
markov Avatar asked Nov 08 '22 21:11

markov


1 Answers

It's doing this intentionally. If users are using swipe gestures to navigate. If you navigate into a scroll view, the first element in the view should be focused. For sighted VoiceOver users, obviously not scrolling up to the top would be jarring, as potentially your focus rectangle could be off screen. This is a feature, not a bug.

like image 119
ChrisCM Avatar answered Nov 14 '22 23:11

ChrisCM