美文网首页iOS面试那些事iOS Developer程序员
iOS自动布局2 —intrinsic content size

iOS自动布局2 —intrinsic content size

作者: 流水_事 | 来源:发表于2017-04-06 09:13 被阅读84次

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

    (这里使用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];
    

    最后一句被注释的结果:

    compress1

    去掉注释后的结果:

    compress2

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

    相关文章

      网友评论

        本文标题:iOS自动布局2 —intrinsic content size

        本文链接:https://www.haomeiwen.com/subject/ujpfattx.html