使用约束布局该如何设置哪个视图(UILabel)的内容优先被压缩?

引言

在实际项目开发中,约束布局给我们带来了很大的便利,可以帮助我们创建灵活且响应迅速的用户界面。通常情况下,它都能很好地工作,但在一些包含许多UILabel的场景中,比如会话列表的UI,哪个视图会被优先压缩可能变得有些不可控。

在这篇博客中,我们将探讨如何使用内容压缩阻力优先级(Content Compression Resistance Priority)来解决这个问题,从而使我们的页面元素更加可控、更美观。

遇到问题

在开发会话列表UI时,我们经常会遇到多个UILabel排布在一起的情况。默认情况下,系统会根据内容大小自动决定哪个UILabel的内容会被压缩。

然而,在某些场景下,我们希望某些UILabel的内容能够优先显示完全,而另一些UILabel的内容可以被压缩。比如上面的例子,我们希望用户的性别,消息的时间,还有用户的等级和其它的小标签都能显示全,然后压缩用户昵称。

上面单个列表中的所有子控件都被添加到contentView上,控件的布局代码如下:

        // 头像
        avatarImageView.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(16.0)
            make.centerY.equalToSuperview()
            make.width.height.equalTo(52.0)
        }
        // 昵称
        nameLabel.snp.makeConstraints { make in
            make.leading.equalTo(avatarImageView.snp.trailing).offset(12.0)
            make.top.equalTo(avatarImageView).offset(5.7)
            make.height.equalTo(19.0)
        }
        // 内容
        contentLabel.snp.makeConstraints { make in
            make.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 in
            make.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 in
            make.leading.equalTo(sexAgeView.snp.trailing).offset(4.0)
            make.centerY.equalTo(sexAgeView)
            make.height.equalTo(15.0)
        }
        // 时间
        conversationTimeLabel.snp.makeConstraints { make in
            make.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 = .black
        nameLabel.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的显示效果,确保重要信息能够优先显示完全。希望这篇博客能帮助你更好地理解和应用这个重要的概念,使你的界面更加灵活和美观。

  • 10
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牙科就诊管理系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线查看数据。管理员管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等功能。牙科就诊管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 管理员在后台主要管理病例管理、字典管理、公告管理、药单管理、药品管理、药品收藏管理、药品评价管理、药品订单管理、牙医管理、牙医收藏管理、牙医评价管理、牙医挂号管理、用户管理、管理员管理等。 牙医列表页面,此页面提供给管理员的功能有:查看牙医、新增牙医、修改牙医、删除牙医等。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。药品管理页面,此页面提供给管理员的功能有:新增药品,修改药品,删除药品。药品类型管理页面,此页面提供给管理员的功能有:新增药品类型,修改药品类型,删除药品类型。
您可以按照以下代码来进行布局: ```swift import SnapKit class YourTableViewCell: UITableViewCell { private let label = UILabel() private let imageView = UIImageView() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) // Add subviews to contentView contentView.addSubview(label) contentView.addSubview(imageView) // Set label properties label.numberOfLines = 0 // Set constraints for label label.snp.makeConstraints { make in make.top.equalToSuperview().offset(5) make.left.right.equalToSuperview() } // Set constraints for imageView imageView.snp.makeConstraints { make in make.top.equalTo(label.snp.bottom).offset(10) make.left.right.equalToSuperview() make.bottom.equalToSuperview().offset(-10) make.height.equalTo(0) } } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure(with text: String, image: UIImage?) { label.text = text // Update constraints for imageView based on the presence of an image if let image = image { imageView.image = image imageView.snp.updateConstraints { make in make.height.equalTo(50) make.top.equalTo(label.snp.bottom).offset(10) make.bottom.equalToSuperview().offset(-10) } } else { imageView.image = nil imageView.snp.updateConstraints { make in make.height.equalTo(0) make.top.equalTo(label.snp.bottom).offset(0) make.bottom.equalToSuperview().offset(-10) } } } } ``` 在上述代码中,我们使用了 `snp` 的链式语法来设置布局。我们首先初始化了一个 `UILabel` 和一个 `UIImageView` 并将它们添加到 `contentView` 上。然后,我们设置了 `UILabel` 的一些属性,如 `numberOfLines` 来使其多行显示。接着,我们设置了 `UILabel` 和 `UIImageView` 的约束。在 `configure(with:image:)` 方法中,我们根据传递进来的 `image` 参数来更新 `UIImageView` 的约束。如果 `image` 不为 `nil`,则我们将 `UIImageView` 的高度设置为 50,并将其放置在 `UILabel` 的下方。如果 `image` 为 `nil`,则我们将 `UIImageView` 的高度设置为 0,使其不可见,并将其放置在 `UILabel` 的正下方。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值