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

1

5

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
Claypool answered 14/1, 2016 at 15:21 Comment(0)
B
1

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.

Britannia answered 15/1, 2016 at 14:23 Comment(4)
Well, If this is a feature then why is it absent in iOS 9.x? also it doesn't scroll to the start when obtaining focus again, only on first view appearClaypool
As a disabled user, you wouldn't want this happening on focus every time. Should you remove focus from the view and come back, you'd expect the view to be where you left it (See WCAG 2.0). Features do change from OS to OS. Otherwise there wouldn't be a 9.x.Britannia
@ChrisCM could you have a look at stackoverflow.com/users/1046037/user1046037, happens every time for me. Problem sometimes it gets hidden under the overlayPoultry
That doesn't seem to link to a question, but to your profile...?Britannia

© 2022 - 2024 — McMap. All rights reserved.