引言
在实际项目开发中,约束布局给我们带来了很大的便利,可以帮助我们创建灵活且响应迅速的用户界面。通常情况下,它都能很好地工作,但在一些包含许多UILabel的场景中,比如会话列表的UI,哪个视图会被优先压缩可能变得有些不可控。
在这篇博客中,我们将探讨如何使用内容压缩阻力优先级(Content Compression Resistance Priority)来解决这个问题,从而使我们的页面元素更加可控、更美观。
遇到问题
在开发会话列表UI时,我们经常会遇到多个UILabel排布在一起的情况。默认情况下,系统会根据内容大小自动决定哪个UILabel的内容会被压缩。
然而,在某些场景下,我们希望某些UILabel的内容能够优先显示完全,而另一些UILabel的内容可以被压缩。比如上面的例子,我们希望用户的性别,消息的时间,还有用户的等级和其它的小标签都能显示全,然后压缩用户昵称。
上面单个列表中的所有子控件都被添加到contentView上,控件的布局代码如下:
// 头像avatarImageView.snp.makeConstraints { make inmake.leading.equalToSuperview().offset(16.0)make.centerY.equalToSuperview()make.width.height.equalTo(52.0)}// 昵称nameLabel.snp.makeConstraints { make inmake.leading.equalTo(avatarImageView.snp.trailing).offset(12.0)make.top.equalTo(avatarImageView).offset(5.7)make.height.equalTo(19.0)}// 内容contentLabel.snp.makeConstraints { make inmake.leading.equalTo(nameLabel)make.trailing.equalToSuperview().offset(-36.0)make.top.equalTo(nameLabel.snp.bottom).offset(4.0)make.height.equalTo(17.0)}// 性别sexAgeView.snp.makeConstraints { make inmake.leading.equalTo(nameLabel.snp.trailing).offset(4.0)make.centerY.equalTo(nameLabel)make.width.equalTo(18.0)make.height.equalTo(15.0)}// 等级levelView.snp.makeConstraints { make inmake.leading.equalTo(sexAgeView.snp.trailing).offset(4.0)make.centerY.equalTo(sexAgeView)make.height.equalTo(15.0)}// 时间conversationTimeLabel.snp.makeConstraints { make inmake.leading.greaterThanOrEqualTo(levelView.snp.trailing).offset(4.0)make.trailing.equalToSuperview().offset(-16.0)make.centerY.equalTo(nameLabel)make.height.equalTo(17.0)}
如果我们什么都不设置,在iOS 17.5.1上显示如下:
细心一点的话会发现,消息的时间不见了,应该是宽度被压缩成了0,等级标签倒是良好。性别由于这里面没有年龄数据将宽度设为固定值,所以倒不存在压缩的问题了。
这样随机的压缩视图,让我们感到不太妙,那有没有什么方案可以设置谁来优先压缩呢?
压缩阻力优先级的基本概念
当然是有的,为了解决这个问题我们先来了解一下压缩阻力优先级的基本概念,内容压缩阻力优先级(Content Compression Resistance Priority)它决定了一个视图在受到压缩时的优先级。优先级越高,视图越不容易被压缩。每个视图都有一个水平和垂直方向的内容压缩阻力优先级,默认值为750。
视图提供了一个个方法可以修改它的压缩阻力优先级:
open func setContentCompressionResistancePriority(_ priority: UILayoutPriority, for axis: NSLayoutConstraint.Axis)
该方法设置视图在收到压缩时压缩阻力的优先级(Content Compression Resistance Priority),优先级越高视图越不容易被压缩。
相对应的还有一个内容拥抱优先级(Content Hugging Priority),我们将在下篇博客来介绍它。
如何设置内容压缩阻力优先级
还以上面的布局为例,我们需要考虑的视图应该有三个:
- nameLabel
- levelView
- conversationTimeLabel
在没有进行任何设置之前,先来看一下它们的优先级:
18:56:07.987 💚 DEBUG CSNormalConversationListCell.setupView():44 - nameLabel - UILayoutPriority(rawValue: 750.0)
18:56:07.988 💚 DEBUG CSNormalConversationListCell.setupView():57 - levelView - UILayoutPriority(rawValue: 750.0)
18:56:07.988 💚 DEBUG CSNormalConversationListCell.setupView():63 - conversationTimeLabel - UILayoutPriority(rawValue: 750.0)
可以看见在没有修改之前,优先级都是750,我们希望的是优先压缩nameLabel,使得另外两个组件保持完整。那我们就降低nameLabel的压缩阻力优先级,比如设置为.defaultLow另外两个组件保持不变,代码如下:
// 昵称contentView.addSubview(nameLabel)nameLabel.font = CSFontDefine.pingFang(weight: .medium, size: 16.0)nameLabel.textColor = .blacknameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)CSLog.debug(module: "nameLabel - ", nameLabel.contentCompressionResistancePriority(for: .horizontal))
控制台打印结果如下:
18:59:01.330 💚 DEBUG CSNormalConversationListCell.setupView():44 - nameLabel - UILayoutPriority(rawValue: 250.0)
已经降低了nameLabel压缩阻力值,我们来看下效果:
现在就已经得到了我们想要的结果。
结语
压缩阻力优先级的概念至关重要,通过使用内容压缩阻力优先级,我们可以更好地控制UI中各个UILabel的显示效果,确保重要信息能够优先显示完全。希望这篇博客能帮助你更好地理解和应用这个重要的概念,使你的界面更加灵活和美观。