当contentSize更改时,UIScrollView会调整contentOffset

时间:2011-06-29 15:29:54

标签: ios iphone uiscrollview contentsize

我正在调整详细视图控制器的状态,就在它被推到navigationController之前:

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

DetailViewController中,scrollView驻留。我根据传递的对象调整了哪些内容:

- (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;
}

现在,这一切都有效,但scrollView会在navigationController的滑入式动画中调整它contentOffsetcontentOffset将设置为最后一个contentSize与新计算的一个之间的差异。这意味着第二次打开detailsView时,详细信息将滚动到某个不需要的位置。即使我明确地将contentOffset设置为CGPointZero

我发现重置contentOffset中的- viewWillAppear无效。我能想到的最好的方法是重置viewDidAppear中的contentOffset,导致内容明显上下移动:

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

有没有办法阻止UIScrollViewcontentOffset更改后contentSize进行调整?

8 个答案:

答案 0 :(得分:58)

使用UIViewController推送包含UIScrollView的{​​{1}}时发生。

iOS 7

解决方案1(代码)

@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets设为UINavigationController

解决方案2(故事板)

取消选中NO

Adjust Scroll View Insets

iOS 6

解决方案(代码)

Adjust Scroll View Insets中设置UIScrollView的属性contentOffsetcontentInset。示例代码:

viewWillLayoutSubviews

答案 1 :(得分:15)

虽然我找到了解决方案,但问题的原因仍不清楚。通过在调整内容大小和偏移量之前重置它们,UIScrollView将不会设置动画:

- (void)detailsForObject:(id)someObject {
    // These 2 lines solve the issue:
    self.scrollView.contentSize = CGSizeZero;
    self.scrollView.contentOffset = CGPointZero;

    // 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;
}

答案 2 :(得分:2)

我在UIScrollview中遇到了同样的问题,问题是由于没有设置contentSize引起的。将contentSize设置为项目数后,问题就解决了。

self.headerScrollView.mainScrollview.contentSize = CGSizeMake(320 * self.sortedMaterial.count, 0);

答案 3 :(得分:1)

这对我有用:
在情节提要中,在scrollView的“大小”检查器中,将“内容插入调整行为”设置为“从不”。

enter image description here

答案 4 :(得分:0)

您的scrollView是DetailViewController的根视图吗?如果是,请尝试将scrollView包装在普通UIView中,并将后者作为DetailViewController的根视图。由于UIView没有contentOffset属性,因此它们不受导航控制器进行的内容偏移调整的影响(由于导航栏等)。

答案 5 :(得分:0)

我遇到了问题,对于特定情况 - 我没有调整大小 - 我使用了以下内容:

float position = 100.0;//for example

SmallScroll.center = CGPointMake(position + SmallScroll.frame.size.width / 2.0, SmallScroll.center.y);

同样适用于y:anotherPosition + SmallScroll.frame.size.height / 2.0

因此,如果您不需要调整大小,这是一个快速而轻松的解决方案。

答案 6 :(得分:0)

我遇到了类似的问题,UIKit在推送动画期间设置了scrollView的contentOffset。

这些解决方案都不适合我,可能是因为我支持iOS 10和iOS 11。

我能够通过将滚动视图子类化以防止UIKit在将滚动视图从窗口中移除后更改偏移量来解决问题:

/// A Scrollview that only allows the contentOffset to change while it is in the window hierarchy. This can keep UIKit from resetting the `contentOffset` during transitions, etc.
class LockingScrollView: UIScrollView {
    override var contentOffset: CGPoint {
        get {
            return super.contentOffset
        }
        set {
            if window != nil {
                super.contentOffset = newValue
            }
        }
    }
}

答案 7 :(得分:0)

补充凯伦安妮的回答:

iOS 11+

automaticallyAdjustsScrollViewInsets 已弃用

改用这个:

故事板:

enter image description here

代码(Swift):

scrollView.contentInsetAdjustmentBehavior = .never