无法让 UIView sizeToFit 做任何有意义的事情

发布于 2024-09-27 13:04:40 字数 1217 浏览 3 评论 0 原文

当我向 UIView 添加子视图时,或者当我调整现有子视图的大小时,我期望 [view sizeToFit][view sizeThatFits]以反映这种变化。但是,我的经验是 sizeToFit 不执行任何操作,并且 sizeThatFits 在更改之前和之后返回相同的值。

我的测试项目有一个包含单个按钮的视图。单击该按钮会向视图添加另一个按钮,然后在包含的视图上调用 sizeToFit。在添加子视图之前和之后,视图的边界都会转储到控制台。

- (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];
}

输出是:

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}

我一定在这里遗漏了一些东西。

谢谢。

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.

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

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

发布评论

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

评论(4

恋竹姑娘 2024-10-04 13:04:40

文档对此非常清楚。 -sizeToFit 几乎调用 -sizeThatFits: (可能以视图的当前大小作为参数),并且 -sizeThatFits: 的默认实现确实如此几乎什么都没有(它只是返回它的参数)。

某些 UIView 子类会重写 -sizeThatFits: 来执行更有用的操作(例如 UILabel)。如果您想要任何其他功能(例如调整视图大小以适合其子视图),您应该子类化 UIView 并重写 -sizeThatFits:

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:.

勿忘心安 2024-10-04 13:04:40

如果你不重写 UIView,你可以只使用扩展。

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
    }

}

相同的代码,但速度快了 3 倍:

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

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)
    }
}
流年已逝 2024-10-04 13:04:40

您可以单独使用 IB (xcode 4.5) 执行类似操作:

  1. 单击
  2. “大小”检查器中的 UIView,将 content Hugging 拖动到 1(水平和垂直)
  3. 拖动 constraints 下将>compressionresistance 更改为 1000(两者均适用),
  4. 单击 Width 并将 priority 更改为 250
  5. 对高度
  6. 您可以使用UIViewinset来控制左/右/上/下的填充

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
孤独患者 2024-10-04 13:04:40
        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;

这对我有用。

        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.

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