同一层级多个自动调整大小的视图的约束(Content Hugging Priority和Content Compression Resistance Priority

接到一个需求是这样的,在同一行里左边、中间、右边文字长度都不是固定的,不知道谁长谁短,而且还有一个要求就是中间文字在一行中有足够空间就靠右显示,如果这一行满了,就两行靠左显示。需求显示如下图:


视图1

其实如果想做到这种约束需要使用这两个约束设置,分别是Content Hugging PriorityContent Compression Resistance Priority

许多人可能对这两个属性比较陌生,这两个属性对有intrinsic content size的控件(例如button,label)非常重要.
注:具有intrinsic content size的控件当你设置内容后,它可以根据内容多少来调整自己大小.

一.Content Hugging Priority

  • 抗拉伸优先级,
  • 值越小,视图越容易被拉伸

使用场景:
当一个父视图固定,并且父视图上有多个intrinsic content size的控件的时候,在这几个视图内容总和不够填充父视图区域时,此属性可以控制优先拉伸哪个视图内容.

比如上边视图1中的第一行,左右都比较短,然后就拉伸了中间的label,主要就是设置了中间label的 Content Hugging Priority 的 Horizontal 优先级小于左右label的优先级。

约束设置如下图:


视图2

当前约束是中间label的约束,可以看到视图2中标记为1的地方优先级为250,其实左右两个这里的约束为251,所以当这一行当中这些视图不足以填充满整一行的时候,因为他的抵抗拉伸优先级小,所以这个优先级小的就会被拉伸来填充满整一行。

二. Content Compression Resistance Priority

  • 视图抗压缩优先级,
  • 值越小,视图越容易被压缩

可以看到视图2中标记为2的地方的优先级为250(大小值随意只要小于750就行),左右两个label此位置的优先级为750,因为250小于750,所以抵抗压缩优先级就小,在视图1中第二、第三、第四行可以看出来中间的label是被压缩的,尤其是第四行,当空间完全不足的时候,中间的lable直接就消失了。

至于中间label靠左靠右显示需要动态计算,中间label xib设置属性lines为2,代码如下:

func configData(_ left: String, center: String, right: String) {
        leftLabel.text = left
        centerLabel.text = center
        rightLabel.text = right
        centerLabel.textAlignment = .right
        
        setNeedsLayout()
        layoutIfNeeded()
        let attributes = NSMutableAttributedString.init(string: center)
        let width = attributes.boundingRect(with: CGSize(width: 0, height: 16), options: [.usesFontLeading, .usesLineFragmentOrigin], context: nil).size.width
        let rightLabelLeft = rightLabel.frame.origin.x - 10;
        let leftLableRight = leftLabel.frame.origin.x + leftLabel.frame.size.width + 20
        if (rightLabelLeft - leftLableRight) < width {
            centerLabel.textAlignment = .left
        }
        
    }

因中间label距离左右视图间距分别为20、10,所以计算这一行总宽度减去左右视图以及间距以后剩余的宽度,如果此宽度小于中间要显示文字的宽度的时候就需要两行显示了,这个时候就设置靠左显示,因为xib上边中间label默认设置靠右显示的。

修改如下:


视图3

当视图3中圈起来的值修改为751大于左右lable的750时,对应的显示效果如下图:


视图4

这个时候中间label的抗压缩优先级大于左右两个label的抗压缩优先级,所以中间label就不容易被压缩,那么就压缩了左右两个label的宽度,可以看到第四行右边label已经消失了。

setNeedsLayout()、layoutIfNeeded()用法请转移至setNeedsLayout和layoutIfNeeded

还有不明白的可以下载demo看一下。

本人原文博客地址
demo地址

你可能感兴趣的:(同一层级多个自动调整大小的视图的约束(Content Hugging Priority和Content Compression Resistance Priority)