iOS自动布局2 —intrinsic content size, compression resistance, content hugging

之前说到自动布局的关键就是给出正确且完整的约束。那么看一下下面的例子给出的例子约束是否完整:

(这里使用Masonry来描述约束,可以参考https://github.com/SnapKit/Masonry,但是我觉得直接看也能够看得懂了)

    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont systemFontOfSize:15];
    label.text = @"Hello";
    [self.view addSubview:label];
    [label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left).offset(16);
        make.top.equalTo(self.view.mas_top).offset(16);
    }];

这里只定义了两个约束,left 和 top,只够计算出frame的originX和orginY,没有width和height。那么是不是属于不完整的约束呢?其实在这里给出的约束已经是完整的了。因为对于UILabel这个控件而言 ,只要通过其font和text系统就可以计算出Label该有的长度和宽度。这里的长度和宽度就是UILabel的intrinsic content size(固有属性)。

官方文档给出的视图与intrinsic content size:

View Intrinsic content size
UIView and NSView No intrinsic content size.
Sliders Defines only the width
Labels, buttons, switches, and text fields Defines both the height and the width.
Text views and image views Intrinsic content size can vary.

那么对于具有intrinsic content size的视图来说,是不是意味着自动帮该这些视图添加了像width=a,height=b这样的约束呢?

这里,其实在布局的时候会添加四个约束(对于height 和 width均有intrinsic size的情况下):

  1. // Compression Resistance
  2. View.height >= IntrinsicHeight
  3. View.width >= IntrinsicWidth
  4. // Content Hugging
  5. View.height <= IntrinsicHeight
  6. View.width <= IntrinsicWidth

compression resistance

2,3为抗压缩约束,防止视图被压缩,约束默认的优先级为750(UILayoutPriorityDefaultHigh)。设置的API为:

- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis

axis参数表示方向,水平或者垂直。

content hugging

6,7约束防止视图被拉伸,约束的默认优先级为250(UILayoutPriorityDefaultLow)。设置的API为:

- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis

应用

一般我们会如何运用compression resistance 和 content hugging呢?

给出一个比较常见的需求:

在同一行中显示标题和时间,时间必须显示完全,标题如果太长就截取可显示的部分,剩余的用…表示。

代码如下:

    UILabel *titleLabel = [[UILabel alloc] init];
    [self.view addSubview:titleLabel];
    titleLabel.text = @"Each of these constraints can have its own priority. By default, ";
    [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left).offset(16);
        make.top.equalTo(self.view.mas_top).offset(100);
    }];
    
    UILabel *timeLabel = [[UILabel alloc] init];
    timeLabel.text = @"2017/03/12 18:20:22";
    [self.view addSubview:timeLabel];
    [timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(titleLabel.mas_right).offset(8);
        make.top.equalTo(titleLabel.mas_top);
        make.right.lessThanOrEqualTo(self.view.mas_right).offset(-8);
    }];
//    [timeLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];

最后一句被注释的结果:

iOS自动布局2 —intrinsic content size, compression resistance, content hugging_第1张图片
compress1

去掉注释后的结果:

iOS自动布局2 —intrinsic content size, compression resistance, content hugging_第2张图片
compress2

这是因为去掉注释后,timeLabel的水平抗压缩约束的优先级(required,1000)高于titleLabel的优先级(750)。所以这里被压缩的是titleLabel。同理也可应用于content hugging,只是将方向方向改变一下。

你可能感兴趣的:(iOS自动布局2 —intrinsic content size, compression resistance, content hugging)