如何调整超级视图的大小以适应所有带有自动布局的子视图? [英] How to resize superview to fit all subviews with autolayout?

查看:26
本文介绍了如何调整超级视图的大小以适应所有带有自动布局的子视图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对自动布局的理解是,它采用父视图的大小,并根据约束和内在大小计算子视图的位置.

My understanding of autolayout is that it takes the size of superview and base on constrains and intrinsic sizes it calculates positions of subviews.

有没有办法扭转这个过程?我想根据约束和内在大小调整超级视图的大小.实现这一目标的最简单方法是什么?

Is there a way to reverse this process? I want to resize superview on the base of constrains and intrinsic sizes. What is the simplest way of achieving this?

我在 Xcode 中设计了视图,我将其用作 UITableView 的标头.该视图包括一个标签和一个按钮.标签的大小因数据而异.根据约束,标签成功按下按钮,或者如果按钮和超级视图底部之间存在约束,则标签被压缩.

I have view designed in Xcode which I use as a header for UITableView. This view includes a label and a button. Size of the label differs depending on data. Depending on constrains the label successfully pushes the button down or if there is a constrain between the button and bottom of superview the label is compressed.

我发现了一些类似的问题,但没有很好且简单的答案.

I have found a few similar questions but they don’t have good and easy answers.

推荐答案

要使用的正确 API 是 UIView systemLayoutSizeFittingSize:,传递 UILayoutFittingCompressedSizeUILayoutFittingExpandedSize.

The correct API to use is UIView systemLayoutSizeFittingSize:, passing either UILayoutFittingCompressedSize or UILayoutFittingExpandedSize.

对于使用自动布局的普通 UIView,只要您的约束正确,它就应该可以工作.如果你想在 UITableViewCell 上使用它(例如确定行高),那么你应该在你的单元格 contentView 上调用它并获取高度.

For a normal UIView using autolayout this should just work as long as your constraints are correct. If you want to use it on a UITableViewCell (to determine row height for example) then you should call it against your cell contentView and grab the height.

如果您的视图中有一个或多个 UILabel 是多行的,则需要进一步考虑.对于这些,必须正确设置 preferredMaxLayoutWidth 属性,以便标签提供正确的 intrinsicContentSize,它将用于 systemLayoutSizeFittingSize's 计算.

Further considerations exist if you have one or more UILabel's in your view that are multiline. For these it is imperitive that the preferredMaxLayoutWidth property be set correctly such that the label provides a correct intrinsicContentSize, which will be used in systemLayoutSizeFittingSize's calculation.

根据要求,添加表格视图单元格的高度计算示例

使用自动布局计算表格单元格的高度并不是非常有效,但它确实很方便,特别是如果您有一个具有复杂布局的单元格.

Using autolayout for table-cell height calculation isn't super efficient but it sure is convenient, especially if you have a cell that has a complex layout.

正如我上面所说,如果您使用多行 UILabel,则必须将 preferredMaxLayoutWidth 同步到标签宽度.我使用自定义 UILabel 子类来执行此操作:

As I said above, if you're using a multiline UILabel it's imperative to sync the preferredMaxLayoutWidth to the label width. I use a custom UILabel subclass to do this:

@implementation TSLabel

- (void) layoutSubviews
{
    [super layoutSubviews];

    if ( self.numberOfLines == 0 )
    {
        if ( self.preferredMaxLayoutWidth != self.frame.size.width )
        {
            self.preferredMaxLayoutWidth = self.frame.size.width;
            [self setNeedsUpdateConstraints];
        }
    }
}

- (CGSize) intrinsicContentSize
{
    CGSize s = [super intrinsicContentSize];

    if ( self.numberOfLines == 0 )
    {
        // found out that sometimes intrinsicContentSize is 1pt too short!
        s.height += 1;
    }

    return s;
}

@end

这是一个人为的 UITableViewController 子类,用于演示 heightForRowAtIndexPath:

Here's a contrived UITableViewController subclass demonstrating heightForRowAtIndexPath:

#import "TSTableViewController.h"
#import "TSTableViewCell.h"

@implementation TSTableViewController

- (NSString*) cellText
{
    return @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
}

#pragma mark - Table view data source

- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView
{
    return 1;
}

- (NSInteger) tableView: (UITableView *)tableView numberOfRowsInSection: (NSInteger) section
{
    return 1;
}

- (CGFloat) tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath
{
    static TSTableViewCell *sizingCell;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        sizingCell = (TSTableViewCell*)[tableView dequeueReusableCellWithIdentifier: @"TSTableViewCell"];
    });

    // configure the cell
    sizingCell.text = self.cellText;

    // force layout
    [sizingCell setNeedsLayout];
    [sizingCell layoutIfNeeded];

    // get the fitting size
    CGSize s = [sizingCell.contentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize];
    NSLog( @"fittingSize: %@", NSStringFromCGSize( s ));

    return s.height;
}

- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
{
    TSTableViewCell *cell = (TSTableViewCell*)[tableView dequeueReusableCellWithIdentifier: @"TSTableViewCell" ];

    cell.text = self.cellText;

    return cell;
}

@end

一个简单的自定义单元格:

A simple custom cell:

#import "TSTableViewCell.h"
#import "TSLabel.h"

@implementation TSTableViewCell
{
    IBOutlet TSLabel* _label;
}

- (void) setText: (NSString *) text
{
    _label.text = text;
}

@end

而且,这是 Storyboard 中定义的约束的图片.请注意,标签上没有高度/宽度限制 - 这些是从标签的 intrinsicContentSize 推断出来的:

And, here's a picture of the constraints defined in the Storyboard. Note that there are no height/width constraints on the label - those are inferred from the label's intrinsicContentSize:

这篇关于如何调整超级视图的大小以适应所有带有自动布局的子视图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆