iPhone UIView - Resize Frame to Fit Subviews

前端 未结 11 1474
时光取名叫无心
时光取名叫无心 2020-12-04 17:51

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

相关标签:
11条回答
  • 2020-12-04 18:14

    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]
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-04 18:17

    Whatever module that dynamically added all these subviews had to know where to put them (so they relate properly, or so they don't overlap, etc.) Once you know that, plus the size of the current view, plus the size of the subview, you have all you need to determine if the enclosing view needs to be modified.

    0 讨论(0)
  • 2020-12-04 18:19
    [myView sizeToFit];
    

    Should work, why don't you check the CGRect before and after?

    0 讨论(0)
  • 2020-12-04 18:20

    Check out Having trouble getting UIView sizeToFit to do anything meaningful

    The gist is that sizeToFit is for subclasses to override, and doesn't do anything in UIView. It does stuff for UILabel, because it overrides sizeThatFits: which is called by sizeToFit

    0 讨论(0)
  • 2020-12-04 18:21

    Here is a swift version of the accepted answer, also small change, instead of extending it this method gets the view as a variable and returns it.

    func resizeToFitSubviews(#view: UIView) -> UIView {
        var width: CGFloat = 0
        var height: CGFloat = 0
    
        for someView in view.subviews {
            var aView = someView as UIView
            var newWidth = aView.frame.origin.x + aView.frame.width
            var newHeight = aView.frame.origin.y + aView.frame.height
            width = max(width, newWidth)
            height = max(height, newHeight)
        }
    
        view.frame = CGRect(x: view.frame.origin.x, y: view.frame.origin.y, width: width, height: height)
        return view
    }
    

    Heres the extending version:

    /// Extension, resizes this view so it fits the largest subview
    func resizeToFitSubviews() {
        var width: CGFloat = 0
        var height: CGFloat = 0
        for someView in self.subviews {
            var aView = someView as! UIView
            var newWidth = aView.frame.origin.x + aView.frame.width
            var newHeight = aView.frame.origin.y + aView.frame.height
            width = max(width, newWidth)
            height = max(height, newHeight)
        }
    
        frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: width, height: height)
    }
    
    0 讨论(0)
  • 2020-12-04 18:28

    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.

    0 讨论(0)
提交回复
热议问题