Having trouble getting UIView sizeToFit to do anyt

2019-01-17 19:47发布

When I add a subview to a UIView, or when I resize an existing subview, I would expect [view sizeToFit] and [view sizeThatFits] to reflect that change. However, my experience is that sizeToFit does nothing, and sizeThatFits returns the same value before and after the change.

My test project has a single view that contains a single button. Clicking the button adds another button to the view and then calls sizeToFit on the containing view. The bounds of the view are dumped to the console before and after adding the subview.

- (void) logSizes {
 NSLog(@"theView.bounds: %@", NSStringFromCGRect(theView.bounds));
 NSLog(@"theView.sizeThatFits: %@", NSStringFromCGSize([theView sizeThatFits:CGSizeZero])); 
}

- (void) buttonTouched { 
 [self logSizes];
 UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
 btn.frame = CGRectMake(10.0f, 100.0f, 400.0f, 600.0f);
 [theView addSubview:btn];
 [theView sizeToFit];
 [self performSelector:@selector(logSizes) withObject:nil afterDelay:1.0];
}

And the output is:

2010-10-15 15:40:42.359 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:42.387 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}
2010-10-15 15:40:43.389 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:43.391 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}

I must be missing something here.

Thanks.

4条回答
兄弟一词,经得起流年.
2楼-- · 2019-01-17 19:51

If you won't override UIView, u can just use extension.

Swift:

extension UIView {

    func sizeToFitCustom () {
        var size = CGSize(width: 0, height: 0)
        for view in self.subviews {
            let frame = view.frame
            let newW = frame.origin.x + frame.width
            let newH = frame.origin.y + frame.height
            if newW > size.width {
                size.width = newW
            }
            if newH > size.height {
                size.height = newH
            }
        }
        self.frame.size = size
    }

}

The same code but 3 times faster:

extension UIView {
    final func sizeToFitCustom() {
        var w: CGFloat = 0,
            h: CGFloat = 0
        for view in subviews {
            if view.frame.origin.x + view.frame.width > w { w = view.frame.origin.x + view.frame.width }
            if view.frame.origin.y + view.frame.height > h { h = view.frame.origin.y + view.frame.height }
        }
        frame.size = CGSize(width: w, height: h)
    }
}
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-17 20:05

The documentation is pretty clear on this. -sizeToFit pretty much calls -sizeThatFits: (probably with the view's current size as the argument), and the default implementation of -sizeThatFits: does almost nothing (it just returns its argument).

Some UIView subclasses override -sizeThatFits: to do something more useful (e.g. UILabel). If you want any other functionality (such as resizing a view to fit its subviews), you should subclass UIView and override -sizeThatFits:.

查看更多
不美不萌又怎样
4楼-- · 2019-01-17 20:13
        self.errorMessageLabel.text = someNewMessage;

    // We don't know how long the given error message might be, so let's resize the label + containing view accordingly
    CGFloat heightBeforeResize = self.errorMessageLabel.frame.size.height;

    [self.errorMessageLabel sizeToFit];

    CGFloat differenceInHeightAfterResize = self.errorMessageLabel.frame.size.height - heightBeforeResize;

    self.errorViewHeightContstraint.constant = kErrorViewHeightConstraintConstant + differenceInHeightAfterResize;

This worked for me.

查看更多
Juvenile、少年°
5楼-- · 2019-01-17 20:15

You can do some like that using IB alone (xcode 4.5):

  1. Click on the UIView
  2. in the Size inspector drag content hugging to 1 (both horizontal and vertical)
  3. drag compression resistance to 1000 (for both)
  4. under the UIView's constraints click on Width and change priority to 250
  5. Do the same for Height
  6. You can use the UIView's inset to control padding for left/right/top/bottom
查看更多
登录 后发表回答