SizeToFit UIScrollView 的内容大小

发布于 2024-09-28 20:10:00 字数 264 浏览 6 评论 0原文

UIView 有一个 SizeToFit 方法,可以使 UIView 适合它的所有子视图。有没有类似的东西,它只会返回它计算的大小,而不修改任何视图的框架。

我在 UIScrollView 上有几个子视图,我想在滚动视图的 contentSize 上执行 SizeToFit,而不是它的框架。我必须在 contentSize 上执行此操作,因为我不想增加 UIScrollView 的“实际”大小,并且内容是动态异步加载的,因此当我将子视图添加到 UIScrollView 时我无法手动执行此操作。

A UIView has a SizeToFit method that will make the UIView fit all of it's subviews. Is there anything like that, which will just return the size that it calculates and not modify any view's frame.

I have several subviews on a UIScrollView and I want to do SizeToFit on the scroll view's contentSize, rather than it's frame. I have to do it on the contentSize, because I don't want to increase the "real" size of the UIScrollView, and the content is loaded dynamically and asynchronously so I can't do it manually when I add the subviews to the UIScrollView.

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

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

发布评论

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

评论(10

蓦然回首 2024-10-05 20:10:00

目前,这是我最好的:

CGRect contentRect = CGRectZero;
for (UIView *view in self.subviews)
    contentRect = CGRectUnion(contentRect, view.frame);
self.contentSize = contentRect.size;

At the moment, this is the best I have:

CGRect contentRect = CGRectZero;
for (UIView *view in self.subviews)
    contentRect = CGRectUnion(contentRect, view.frame);
self.contentSize = contentRect.size;
<逆流佳人身旁 2024-10-05 20:10:00

如果您的函数被频繁调用,您不会希望每次都迭代子视图。相反,每当添加子视图时,都会将当前 contentSize 和新子视图的框架进行并集。

- (void)didAddSubview:(UIView *)subview {
    CGRect tmp;
    tmp.origin = CGPointZero;
    tmp.size = self.contentSize;
    tmp = CGRectUnion(tmp,subview.frame);
    self.contentSize = tmp.size;
}

If your function is called frequently, you wouldn't want to iterate over the subviews each time. Instead, whenever a subview is added, do a union of the current contentSize and the frame of the new subview.

- (void)didAddSubview:(UIView *)subview {
    CGRect tmp;
    tmp.origin = CGPointZero;
    tmp.size = self.contentSize;
    tmp = CGRectUnion(tmp,subview.frame);
    self.contentSize = tmp.size;
}
留一抹残留的笑 2024-10-05 20:10:00

在这里找到了解决方案 ScrollView ContentSize,您将能够找到子视图并查找组合内容大小以及表示子视图是水平还是垂直排列的选项。

以下是上面链接中的代码:

@interface UIScrollView(auto_size)
- (void) adjustHeightForCurrentSubviews: (int) verticalPadding;
- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding;
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding;
@end

@implementation UIScrollView(auto_size)
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding {
    float contentWidth = horizontalPadding;
    float contentHeight = verticalPadding;
    for (UIView* subview in self.subviews) {
        [subview sizeToFit];
        contentWidth += subview.frame.size.width;
        contentHeight += subview.frame.size.height;
    }

    contentWidth = changeWidth ? contentWidth : self.superview.frame.size.width;
    contentHeight = changeHeight ? contentHeight : self.superview.frame.size.height;

    NSLog(@"Adjusting ScrollView size to %fx%f, verticalPadding=%d, horizontalPadding=%d", contentWidth, contentHeight, verticalPadding, horizontalPadding);
    self.contentSize = CGSizeMake(contentWidth, contentHeight);
}

- (void) adjustHeightForCurrentSubviews: (int) verticalPadding {
    [self adjustWidth:NO andHeight:YES withHorizontalPadding:0 andVerticalPadding:verticalPadding];
}

- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding {
    [self adjustWidth:YES andHeight:NO withHorizontalPadding:horizontalPadding andVerticalPadding:0];
}
@end

另请务必查看博客页面上的评论,因为提供了替代解决方案。

-阿努普

Found a solution here ScrollView ContentSize, you will be able to find the sizes of the subviews and find the combined content size and also options to say whether subviews are arranged horizontally or vertically.

Here is the code from the link above :

@interface UIScrollView(auto_size)
- (void) adjustHeightForCurrentSubviews: (int) verticalPadding;
- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding;
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding;
@end

@implementation UIScrollView(auto_size)
- (void) adjustWidth: (bool) changeWidth andHeight: (bool) changeHeight withHorizontalPadding: (int) horizontalPadding andVerticalPadding: (int) verticalPadding {
    float contentWidth = horizontalPadding;
    float contentHeight = verticalPadding;
    for (UIView* subview in self.subviews) {
        [subview sizeToFit];
        contentWidth += subview.frame.size.width;
        contentHeight += subview.frame.size.height;
    }

    contentWidth = changeWidth ? contentWidth : self.superview.frame.size.width;
    contentHeight = changeHeight ? contentHeight : self.superview.frame.size.height;

    NSLog(@"Adjusting ScrollView size to %fx%f, verticalPadding=%d, horizontalPadding=%d", contentWidth, contentHeight, verticalPadding, horizontalPadding);
    self.contentSize = CGSizeMake(contentWidth, contentHeight);
}

- (void) adjustHeightForCurrentSubviews: (int) verticalPadding {
    [self adjustWidth:NO andHeight:YES withHorizontalPadding:0 andVerticalPadding:verticalPadding];
}

- (void) adjustWidthForCurrentSubviews: (int) horizontalPadding {
    [self adjustWidth:YES andHeight:NO withHorizontalPadding:horizontalPadding andVerticalPadding:0];
}
@end

Also make sure to have a look at the comments on the blog page as an alternative solution is provided.

-anoop

长伴 2024-10-05 20:10:00

我已经制作了一个用于设置滚动视图内容大小的函数,请尝试并享受它

首先编写此函数...

-(void)setContentSizeOfScrollView:(UIScrollView*)scroll
{
    CGRect rect = CGRectZero;

    for(UIView * vv in [scroll subviews])
    {
        rect = CGRectUnion(rect, vv.frame);
    }

    [scroll setContentSize:CGSizeMake(rect.size.width, rect.size.height)];
}

然后在添加所有元素后,只需调用此函数并将您的滚动视图作为参数传递...

[self setContentSizeOfScrollView:self.YourScrollView];

我100%确定它会起作用............

I have made one function for setting content size of scrollView try it and enjoy

First of all write this function...

-(void)setContentSizeOfScrollView:(UIScrollView*)scroll
{
    CGRect rect = CGRectZero;

    for(UIView * vv in [scroll subviews])
    {
        rect = CGRectUnion(rect, vv.frame);
    }

    [scroll setContentSize:CGSizeMake(rect.size.width, rect.size.height)];
}

then after adding all elements just call this function and pass your scroll view as argument.....

[self setContentSizeOfScrollView:self.YourScrollView];

I am 100% sure that it will work.........

最偏执的依靠 2024-10-05 20:10:00

这是 Swift 3.0 的答案

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    var contentRect: CGRect = CGRect.zero
    for view in self.scrollView.subviews {
        debugPrint("view frame \(view.frame)")
        contentRect = contentRect.union(view.frame)
        debugPrint("frame \(contentRect)")
    }
    self.scrollView.contentSize = contentRect.size
    debugPrint("content size \(self.scrollView.contentSize)")
}

Here is the answer for Swift 3.0

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    var contentRect: CGRect = CGRect.zero
    for view in self.scrollView.subviews {
        debugPrint("view frame \(view.frame)")
        contentRect = contentRect.union(view.frame)
        debugPrint("frame \(contentRect)")
    }
    self.scrollView.contentSize = contentRect.size
    debugPrint("content size \(self.scrollView.contentSize)")
}
暮倦 2024-10-05 20:10:00

虽然 William 的回答非常有用,但它并不能完美工作,因为滚动条也是滚动视图的子视图。事实证明,诀窍是在计算内容大小之前隐藏它们。 Swift 3 代码如下所示:

override func viewDidLayoutSubviews() {
    scrollView.layoutSubviews()

    // disable scrollbars so they don't interfere during resizing
    scrollView.showsVerticalScrollIndicator = false
    scrollView.showsHorizontalScrollIndicator = false

    scrollView.contentSize = scrollView.subViewArea()

    // re-enable the scrollbars
    scrollView.showsVerticalScrollIndicator = true
    scrollView.showsHorizontalScrollIndicator = true
}

您还需要在项目中的某处添加以下扩展:

extension UIScrollView {
    func subViewArea() -> CGSize {
        var rect = CGRect.zero
        for subview in subviews {
            rect = rect.union(subview.frame)
        }

        return rect.size
    }
}

While William's answer was very useful, it didn't work perfectly since the scrollbars are also subviews of the scrollview. Turns out, the trick is to hide them before calculating the content size. Here's what the Swift 3 code would look like:

override func viewDidLayoutSubviews() {
    scrollView.layoutSubviews()

    // disable scrollbars so they don't interfere during resizing
    scrollView.showsVerticalScrollIndicator = false
    scrollView.showsHorizontalScrollIndicator = false

    scrollView.contentSize = scrollView.subViewArea()

    // re-enable the scrollbars
    scrollView.showsVerticalScrollIndicator = true
    scrollView.showsHorizontalScrollIndicator = true
}

You'll also need to add the following extension somewhere in your project:

extension UIScrollView {
    func subViewArea() -> CGSize {
        var rect = CGRect.zero
        for subview in subviews {
            rect = rect.union(subview.frame)
        }

        return rect.size
    }
}
罗罗贝儿 2024-10-05 20:10:00

将一个 UIView 放入具有相同宽度和高度的 UIScrollView 中,并将所有子视图添加到 IT 而不是滚动视图。然后将滚动视图上的clipToBounds属性设置为TRUE,并在UIView上调用sizeToFit。您还可以将 UIView 背景的不透明度设置为 0,使其不可见,但仍显示其子视图。

Put a UIView into the UIScrollView that has the same width and height and add all subviews to IT rather than the scrollview. Then set the clipToBounds property on the scrollview to TRUE, and call sizeToFit on your UIView. You can also set the opacity of the UIView's background to 0 making it invisible, but still showing its subviews.

错爱 2024-10-05 20:10:00

在 swift 2.1 中,将其添加到您的视图控制器中:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let aggregateView = contentView.subviews.reduce(CGRect())
        { aggRect, view in aggRect.union(view.frame) }

    scrollView.contentSize = aggregateView.size

}

In swift 2.1, add this to your view controller:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let aggregateView = contentView.subviews.reduce(CGRect())
        { aggRect, view in aggRect.union(view.frame) }

    scrollView.contentSize = aggregateView.size

}
禾厶谷欠 2024-10-05 20:10:00

联合框架大小来计算内容大小是不够的。因为有时,您的子视图需要重叠,有时子视图之间有边距。您必须了解并计算子视图的起源。

联合方法为 A 和 B 设计提供相同的内容。但是如果您知道最大的最后一个子视图,您可以计算正确的内容高度:

在此处输入图像描述

此扩展可以计算真实内容高度。

extension UIScrollView {

 func adjustContentHeight(bottomPadding: Int = 0) {

    var lastSub: CGRect = .zero
    self.subviews.forEach({
        let sub = $0.frame
        if(sub.maxY > lastSub.maxY) {
            lastSub = sub
        }
    })

    self.contentSize.height = lastSub.maxY + CGFloat(bottomPadding)
 }   
} 

It's not enough that union frame sizes to calculate the content size. Because sometimes, your subview needs to overlap, and sometimes you have margins between subviews. You have to know and calculate origin of subviews.

Union approach gives same content hight for A and B designs. But if you know biggest last subview, you can calculate right content hight:

enter image description here

This extension can calculate the real content height.

extension UIScrollView {

 func adjustContentHeight(bottomPadding: Int = 0) {

    var lastSub: CGRect = .zero
    self.subviews.forEach({
        let sub = $0.frame
        if(sub.maxY > lastSub.maxY) {
            lastSub = sub
        }
    })

    self.contentSize.height = lastSub.maxY + CGFloat(bottomPadding)
 }   
} 
灼痛 2024-10-05 20:10:00

Swift 2 扩展:

用法:

scrollView.contentResize
scrollView.contentWidthResize
scrollView.contentHeightResize

extension UIScrollView {

    ///Will resize content size to fit all subviews.
    func contentResize(){

        var w = CGFloat(0)
        var h = CGFloat(0)

        for view in self.subviews{

            let fw = view.frame.origin.x + view.frame.width
            let fh = view.frame.origin.y + view.frame.height

            w = max(fw, w)
            h = max(fh, h)

        }

        contentSize = CGSize(width: w, height: h)

    }

    ///Will resize content width size to fit all subviews.
    func contentWidthResize(){

        var w = CGFloat(0)

        for view in self.subviews{

            let fw = view.frame.origin.x + view.frame.width

            w = max(fw, w)

        }

        contentSize.width = w

    }

    ///Will resize content height size to fit all subviews.
    func contentHeightResize(){

        var h = CGFloat(0)

        for view in self.subviews{

            let fh = view.frame.origin.y + view.frame.height

            h = max(fh, h)

        }

        contentSize.height = h

    }

}

Swift 2 extension:

Usage:

scrollView.contentResize
scrollView.contentWidthResize
scrollView.contentHeightResize

extension UIScrollView {

    ///Will resize content size to fit all subviews.
    func contentResize(){

        var w = CGFloat(0)
        var h = CGFloat(0)

        for view in self.subviews{

            let fw = view.frame.origin.x + view.frame.width
            let fh = view.frame.origin.y + view.frame.height

            w = max(fw, w)
            h = max(fh, h)

        }

        contentSize = CGSize(width: w, height: h)

    }

    ///Will resize content width size to fit all subviews.
    func contentWidthResize(){

        var w = CGFloat(0)

        for view in self.subviews{

            let fw = view.frame.origin.x + view.frame.width

            w = max(fw, w)

        }

        contentSize.width = w

    }

    ///Will resize content height size to fit all subviews.
    func contentHeightResize(){

        var h = CGFloat(0)

        for view in self.subviews{

            let fh = view.frame.origin.y + view.frame.height

            h = max(fh, h)

        }

        contentSize.height = h

    }

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