Disable [UIScrollView _adjustContentOffsetIfNecessary]

I'm trying to adapt my universal app for different orientations and layouts. I have a UICollectionView with a custom layout.

Whenever the size class changes (especially when switching between full screen and slide over on iPad), the

contentOffset
gets messed up. I've put in some break points and found that the
contentOffset
is being set from a private method
[UIScrollView(UIScrollViewInternal) _adjustContentOffset]
. I can prevent this behaviour by overriding
_adjustContentOffset
and not calling super, however I'm not sure if this is considered using a private API; regardless, its probably not a good idea to completely remove that function.


I also tried setting

automaticallyAdjustsScrollViewInsets = NO
on the UIViewController, but it has no effect. Is there a proper way to disable the contentOffset adjustment?

Replies

In my specific use case, I was changing my custom collection view layout from a horizontal flow to a vertical flow, and I wanted to make sure the same item stayed in the center after the resize. My first attempt was along the lines of:


- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    NSIndexPath *index = [self getCenterIndexPath];

    [self.layout updateLayoutWithContainerSize:size];

    [self scrollToItemAtIndexPath:index];
}


It would scroll correctly, but then

_adjustContentOffsetIfNecessary
would shift the position. I found a way to avoid this, by calling the scroll method inside the coordinator animation block, like this:


- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    NSIndexPath *index = [self getCenterIndexPath];

    [self.layout updateLayoutWithContainerSize:size];

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        [self scrollToItemAtIndexPath:index];
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        [self scrollToItemAtIndexPath:index];
    }];
}


This ensures that the contentOffset is properly adjusted along with the transition and remains in the final position after the transition is complete.


I am still curious about how you can disable the automatic contentOffset adjustment in general, though.

Same issues here. So how to avoid "adjustContentOffsetIfNecessary" anyway?