UIScrollView 内容大小在不应该时裁剪子视图

Posted

技术标签:

【中文标题】UIScrollView 内容大小在不应该时裁剪子视图【英文标题】:UIScrollView content size clipping subviews when it shouldn't 【发布时间】:2012-02-26 17:04:47 【问题描述】:

我有一个 UIScrollView,其中包含几个动态调整大小的子视图。我可以很好地调整子视图的大小和布局,但是当我设置滚动视图本身的内容大小时,底部的子视图会被剪裁。为什么滚动视图的内容大小高度应该大于它包含的视图的高度之和有什么原因?

这是我的情况更详细: 我有一个包含多个子视图的 UIScrollView 的超级视图。在超级视图的 layoutSubviews 方法中,我计算了每个子视图所需的大小,然后设置框架,使子视图垂直平铺在屏幕下方,并在它们之间留出一点空间。完成后,我将 UIScrollView 的内容大小的高度设置为最后一个子视图的结尾(origin.y + size.height)。理论上,这意味着滚动视图的内容区域的底部应该与最后一个子视图的底部完全对齐。

但事实并非如此。相反,最后一个子视图的一大块被剪裁了。它仍然存在 - 如果我向下滚动,我可以在“反弹”期间看到剩余部分。在横向模式下问题更严重 - 底部子视图的大部分根本不可见。

所有子视图都被正确排列和定位。问题是 UIScrollView 的 contentSize 似乎需要明显大于子视图的高度总和(加上它们之间的空间)。这对我来说没有任何意义。此外,大小“关闭”的数量会有所不同 - 我多次使用不同的子视图重复使用此视图,并且它们都关闭了不同的数量。因此,简单地向内容视图高度添加一个常量是没有帮助的。

是什么导致内容大小(或我的身高计算)无法正常工作?

代码:

- (void)layoutSubviews

    [super layoutSubviews];

    CGFloat width = self.bounds.size.width - [self subviewLeftMargin] - [self subviewRightMargin]; // All subviews have same width as parent view

    CGFloat x = [self subviewLeftMargin]; // All subviews should start at the far left of the view 
    CGFloat y = [self spaceBetweenSubviews]; // Running tally of the y coordinate for the next view

    /* Adjust the subviews */
    for(UIView *view in self.theVariousSubviews)   
        /* Resize the view with the desired width, then let it size its height as needed */
        view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, width, view.frame.size.height);
        CGSize newSize = [view sizeThatFits:view.frame.size];

        /* Set the origin */
        //The subviews are positioned correctly, so this doesn't seem to be a problem
        view.frame = CGRectMake(x, y, newSize.width, newSize.height);

        /* Have the view refresh its own layout */
        [view setNeedsLayout];

        /* Update the y value for the next subview */
        y += newSize.height + [self spaceBetweenSubviews];
    

    /* Resize the scroll view to ensure it fits all of the content */
    CGFloat scrollViewHeight = y;
    self.scrollView.contentSize = CGSizeMake(self.scrollView.contentSize.width, scrollViewHeight);
    //Content size is set to the same total height of all subviews and spacing, yet it is too small. Why?

【问题讨论】:

【参考方案1】:

您好,在我看来,您的计算和调整大小的时间是错误的。 如果没有缺少布局更改的代码,我无法完全理解这个问题。

让我印象深刻的是,您分配了 view.frame 两次,并且在新计算之间您使用子布局拦截了该过程,这可能会改变您的计算所依赖的某些值。

我只能建议您将计算与布局分开,并且在计算时不要调用方法。为了让您了解它,您应该删除一个缺少计算的示例应用程序,或者自己添加一些 NSLog 语句,显示任何子视图的帧原始大小和滚动视图的 contentOffset。 根据我的经验,滚动视图通常可以正常工作,因此我预计您的代码中会出现错误。

【讨论】:

以上是关于UIScrollView 内容大小在不应该时裁剪子视图的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 可滚动内容大小歧义

UIScrollView可滚动内容大小模糊

在 UIScrollView 内滚动时,调整大小的 UIWebView 返回到原始大小

当我认为 UIScrollView 不应该垂直滚动时

UIScrollView 不会自动调整大小

UIScrollView 在不正确的点上缩放