iPhone UIView - Resize Frame to Fit Subviews

Viewed 58554

Shouldn't there be a way to resize the frame of a UIView after you've added subviews so that the frame is the size needed to enclose all the subviews? If your subviews are added dynamically how can you determine what size the frame of the container view needs to be? This doesn't work:

[myView sizeToFit];
11 Answers

When you make your own UIView class, consider overriding IntrinsicContentSize in the subclass. This property is called by OS to know the recommended size of your view. I will put code snippet for C# (Xamarin), but the idea is the same:

[Register("MyView")]
public class MyView : UIView
{
    public MyView()
    {
        Initialize();
    }

    public MyView(RectangleF bounds) : base(bounds)
    {
        Initialize();
    }

    Initialize()
    {
        // add your subviews here.
    }

    public override CGSize IntrinsicContentSize
    {
        get
        {
            return new CGSize(/*The width as per your design*/,/*The height as per your design*/);
        }
    }
}

This returned size depends completely on your design. For example, if you just added a label, then width and height is just the width and height of that label. If you have more complex view, you need to return the size that fits all your subviews.

Although quite a few answers already, none worked for my use case. In case you use autoresizingMasks and want to resize view and move subviews so the size of rectangle matches subviews.

public extension UIView {

    func resizeToFitSubviews() {
        var x = width
        var y = height
        var rect = CGRect.zero
        subviews.forEach { subview in
            rect = rect.union(subview.frame)
            x = subview.frame.x < x ? subview.frame.x : x
            y = subview.frame.y < y ? subview.frame.y : y
        }
        var masks = [UIView.AutoresizingMask]()
        subviews.forEach { (subview: UIView) in
            masks.add(subview.autoresizingMask)
            subview.autoresizingMask = []
            subview.frame = subview.frame.offsetBy(dx: -x, dy: -y)
        }
        rect.size.width -= x
        rect.size.height -= y
        frame.size = rect.size
        subviews.enumerated().forEach { index, subview in
            subview.autoresizingMask = masks[index]
        }
    }
}
Related