ios 当 contentSize 改变时 UIScrollView 调整 contentOffset

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6523205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:34:14  来源:igfitidea点击:

UIScrollView adjusts contentOffset when contentSize changes

iosiphoneuiscrollviewcontentsize

提问by Berik

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

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

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

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

DetailViewController一个滚动视图驻留。我根据传递的对象调整了哪些内容:

- (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 contentOffsetduring the navigationController's slide-in animation. The contentOffsetwill 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 contentOffsetto CGPointZeroexplicitly.

现在,这一切都有效,但 scrollView 会contentOffset在 navigationController 的滑入动画期间对其进行调整。在contentOffset将被设置为最后contentSize和新计算之间的差异。这意味着第二次打开 detailsView 时,详细信息将滚动到一些不需要的位置。即使我明确设置contentOffsetCGPointZero

I found that resetting the contentOffsetin - viewWillAppearhas 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:

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

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

Is there a way to prevent a UIScrollViewfrom adjusting its contentOffsetwhen its contentSizeis changed?

有没有办法防止 a在更改时对其进行UIScrollView调整?contentOffsetcontentSize

回答by KarenAnne

Occurs when pushing a UIViewControllercontaining a UIScrollViewusing a UINavigationController.

使用 a推送UIViewController包含 a时发生。UIScrollViewUINavigationController

iOS 7

IOS 7

Solution 1 (Code)

解决方案1(代码)

Set @property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsetsto NO.

设置@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsetsNO

Solution 2 (Storyboard)

解决方案 2(故事板)

Uncheck the Adjust Scroll View Insets

取消选中 Adjust Scroll View Insets

Adjust Scroll View Insets

调整滚动视图插入

iOS 6

iOS 6

Solution (Code)

解决方案(代码)

Set the UIScrollView's property contentOffsetand contentInsetin viewWillLayoutSubviews. Sample code:

设置UIScrollView的属性contentOffsetcontentInsetviewWillLayoutSubviews. 示例代码:

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

回答by Berik

The cause of this problem remains unclear, though I've found a solution. By resetting the content size and offset before adjusting them, the UIScrollView won't animate:

这个问题的原因仍然不清楚,但我已经找到了解决方案。通过在调整内容大小和偏移量之前重置它们,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;
}

回答by Eden

Here's what worked for me:
In the storyboard, in the Size Inspector for the scrollView, set Content Insets Adjustment Behavior to "Never".

这对我
有用:在故事板中,在滚动视图的大小检查器中,将内容插入调整行为设置为“从不”。

enter image description here

在此处输入图片说明

回答by Antoine

I had the same issue with a UIScrollview, where the problem was caused by not setting the contentSize. After setting the contentSize to the number of items this problem was solved.

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

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

回答by Slimebaron

I was experiencing a similar problem, where UIKit was setting the contentOffset of my scrollView during push animations.

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

None of these solutions were working for me, maybe because I was supporting iOS 10 and iOS 11.

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

I was able to fix my issue by subclassing my scrollview to keep UIKit from changing my offsets after the scrollview had been removed from the window:

我能够通过子类化我的滚动视图来解决我的问题,以防止 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
            }
        }
    }
}

回答by Balázs Csordás

I experienced the problem, and for a specific case - I don't adjust the size - I used the following:

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

float position = 100.0;//for example

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

Same would work with y: anotherPosition + SmallScroll.frame.size.height / 2.0

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

So if you don't need to resize, this is a quick and painless solution.

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

回答by octy

Is your scrollView the root view of the DetailViewController? If yes, try wrapping the scrollView in a plain UIViewand make the latter the root view of DetailViewController. Since UIViews don't have a contentOffsetproperty, they are immune to content offset adjustments made by the navigation controller (due to the navigation bar, etc.).

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