Search code examples
iosiphoneuiscrollviewcontentsize

UIScrollView adjusts contentOffset when contentSize changes


I am adjusting a detail view controller's state, just before it is pushed on a navigationController:

[self.detailViewController detailsForObject:someObject];
[self.navigationController pushViewController:self.detailViewController
                                     animated:YES];

In the DetailViewController a scrollView resides. Which content I resize based on the passed object:

- (void)detailsForObject:(id)someObject {
    // set some textView's content here
    self.contentView.frame = <rect with new calculated size>;

    self.scrollView.contentSize = self.contentView.frame.size;
    self.scrollView.contentOffset = CGPointZero;
}

Now, this all works, but the scrollView adjusts it's contentOffset during the navigationController's slide-in animation. The contentOffset will be set to the difference between the last contentSize and the new calculated one. This means that the second time you open the detailsView, the details will scroll to some unwanted location. Even though I'm setting the contentOffset to CGPointZero explicitly.

I found that resetting the contentOffset in - viewWillAppear has no effect. The best I could come up with is resetting the contentOffset in viewDidAppear, causing a noticeable up and down movement of the content:

- (void)viewDidAppear:(BOOL)animated {
    self.scrollView.contentOffset = CGPointZero;
}

Is there a way to prevent a UIScrollView from adjusting its contentOffset when its contentSize is changed?


Solution

  • Occurs when pushing a UIViewController containing a UIScrollView using a UINavigationController.

    iOS 11+

    Solution 1 (Swift Code):

    scrollView.contentInsetAdjustmentBehavior = .never
    

    Solution 2 (Storyboard)

    enter image description here

    iOS 7

    Solution 1 (Code)

    Set @property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets to NO.

    Solution 2 (Storyboard)

    Uncheck the Adjust Scroll View Insets

    Adjust Scroll View Insets

    iOS 6

    Solution (Code)

    Set the UIScrollView's property contentOffset and contentInset in viewWillLayoutSubviews. Sample code:

    - (void)viewWillLayoutSubviews{
      [super viewWillLayoutSubviews];
      self.scrollView.contentOffset = CGPointZero;
      self.scrollView.contentInset = UIEdgeInsetsZero;
    }