Autolayout正在改变旋转时UIScrollView的contentOffset

为了试验autolayout和uiscrollview,我一直在使用这个例子

我已经编辑过在滚动视图中包含2个视图,我已经设置了自动布局约束来将视图水平定位,并将它们的大小设置为填充滚动视图框。

UIView *beeView = [[[NSBundle mainBundle] loadNibNamed:@"BeeView" owner:nil options:nil] firstObject]; beeView.translatesAutoresizingMaskIntoConstraints = NO; [self.scrollView addSubview:beeView]; UIView *beeView2 = [[[NSBundle mainBundle] loadNibNamed:@"BeeView" owner:nil options:nil] firstObject]; beeView2.backgroundColor= [UIColor orangeColor]; beeView2.translatesAutoresizingMaskIntoConstraints = NO; [self.scrollView addSubview:beeView2]; NSDictionary *views = @{@"beeView":beeView,@"beeView2":beeView2, @"scrollView":self.scrollView}; NSDictionary *metrics = @{@"height" : @200}; [self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[beeView(==scrollView)][beeView2(==beeView)]|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:metrics views:views]]; [self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[beeView(==scrollView)]|" options:kNilOptions metrics:metrics views:views]]; 

这很好地产生了我的意图。

但是,如果滚动视图的contentOffset非零并且设备从纵向旋转到横向,则滚动视图的内容偏移将自动设置为32px 。 (见截图) 内容偏移错误

我已经尝试保存contentOffset并在scrollViewDidEndDecelerating:时将其设置为此保存值,但是当滚动视图滚动到32px偏移然后回到我想要的位置时,它会很难看。

如何控制滚动视图的contentOffset ? autolayout约束是否错误? 在调整视图大小时,我可以添加额外的约束来控制contentOffset吗?

32px来自哪里? 它与您的左右scrollView边距有关吗?

每次更换页面时是否保留错误的偏移量? 如果是这种情况,您应该查看您的scrollView的contentInsets值。

否则,我通过分页来管理scrollView上的旋转,就是观察scrollView的contentSize:

首先,在加载视图时,添加观察者:

 [self.scrollView addObserver:self forKeyPath:NSStringFromSelector(@selector(contentSize)) options:0 context:nil]; 

然后,当contentSize值更改时,调整contentOffset:

 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == self.scrollView && [keyPath isEqualToString:NSStringFromSelector(@selector(contentSize))]) { //Note that you should track your page index self.scrollView.contentOffset = CGPointMake(self.pageIndex * self.scrollView.bounds.size.width, self.scrollView.contentOffset.y); } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } 

最后,卸载scrollView时删除观察者:

 [self.scrollView removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentSize)) context:nil]; 

在回顾之前的一些post之后: 一和二 。 您似乎可以按照以下步骤之一找到解决方案:

  1. 以编程方式 :如果您的UIScrollViews的父VC不直接在导航堆栈上 –

编辑

  // Without a Navigation Controller self.automaticallyAdjustsScrollViewInsets = NO; // With a Navigation Controller self.parentViewController.automaticallyAdjustsScrollViewInsets = NO; self.automaticallyAdjustsScrollViewInsets = NO; 
  1. Interface Builder :属性检查器 – >取消选中“布局属性”中的“ 调整滚动视图插入”。

  2. 如果仍然不成功 :在显示的View Controller的ViewWillLayoutSubviews方法中尝试设置以下每个UIScrollView属性:

     self.scrollView.contentOffset = CGPointZero; self.scrollView.contentInset = UIEdgeInsetsZero; 

我猜测选项1和2的组合将起作用,具体取决于导航堆栈的结构。

我知道这是一个老问题,但是如果它对任何人都有用 – 我创建了一个名为LMPageViewUIScrollView子类,它自动应用必要的布局约束并调整旋转时的内容偏移量。 该类作为GitHub上的MarkupKit项目的一部分提供。 用法示例(Swift):

 // Add 3 page views pageView.addPage(view1) pageView.addPage(view2) pageView.addPage(view3) // Show the 3rd page pageView.currentPage = 2 

可以在此处找到使用标记初始化页面视图的其他示例:

  • PageViewController.swift
  • PageViewController.xml