SizeToFit on a UIScrollView's content size

Viewed 21711

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.

10 Answers

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

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)
 }   
} 
Related