UIScrollView 当 contentSize 改变时调整 contentOffset

发布于 2024-11-18 02:50:02 字数 1224 浏览 1 评论 0原文

我正在调整详细视图控制器的状态,就在将其推送到 navigationController 上之前:

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

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

现在,这一切都有效,但滚动视图在导航控制器的滑入动画期间调整其 contentOffsetcontentOffset 将设置为最后一个 contentSize 与新计算的 contentSize 之间的差值。这意味着当您第二次打开详细信息视图时,详细信息将滚动到一些不需要的位置。即使我显式地将 contentOffset 设置为 CGPointZero

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

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

有没有办法阻止 UIScrollView 调整其内容contentOffset 当它的 contentSize 改变时?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

蓝海 2024-11-25 02:50:02

使用 UINavigationController 推送包含 UIScrollViewUIViewController 时发生。

iOS 11+

解决方案 1(Swift 代码):

scrollView.contentInsetAdjustmentBehavior = .never

解决方案 2(故事板)

在此处输入图像描述

iOS 7< /强>

解决方案 1(代码)

设置 @property(nonatomic, allocate) BOOL自动将ScrollViewInsets调整为NO

解决方案 2(故事板)

取消选中调整滚动视图插图

调整滚动视图Insets

iOS 6

解决方案(代码)

设置 UIScrollView 的属性 contentOffsetviewWillLayoutSubviews 中的 contentInset。示例代码:

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

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;
}
神妖 2024-11-25 02:50:02

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

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:

- (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;
}
凑诗 2024-11-25 02:50:02

我对 UIScrollview 遇到了同样的问题,该问题是由于未设置 contentSize 引起的。将 contentSize 设置为项目数后,此问题得到解决。

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

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.

self.headerScrollView.mainScrollview.contentSize = CGSizeMake(320 * self.sortedMaterial.count, 0);
复古式 2024-11-25 02:50:02

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

输入图片此处描述

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

左秋 2024-11-25 02:50:02

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

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

浅忆 2024-11-25 02:50:02

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

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

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

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

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

岁月静好 2024-11-25 02:50:02

我遇到了类似的问题,UIKit 在推送动画期间设置了我的滚动视图的 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
            }
        }
    }
}

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

None of these solutions were working for me, maybe because I was supporting iOS 10 and 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:

/// 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
            }
        }
    }
}
染柒℉ 2024-11-25 02:50:02

添加到 KarenAnne 的答案:

iOS 11+

automaticallyAdjustsScrollViewInsets 已弃用

使用此替代:

故事板:

输入图像描述这里

代码(Swift):

scrollView.contentInsetAdjustmentBehavior = .never

Adding to KarenAnne's answer:

iOS 11+

automaticallyAdjustsScrollViewInsets was deprecated

Use this istead:

Storyboards:

enter image description here

Code (Swift):

scrollView.contentInsetAdjustmentBehavior = .never
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文