UILabel preferredMaxLayout 打破了自我调整大小的单元格
Posted
技术标签:
【中文标题】UILabel preferredMaxLayout 打破了自我调整大小的单元格【英文标题】:UILabel preferredMaxLayout breaking self-sizing cells 【发布时间】:2017-05-23 12:42:00 【问题描述】:我发现 UILabel 无法与 AutoLayout 一起使用的一些非常烦人的问题。
我发现了多个关于此的线程,但没有一个解决方案适合我。
class AudiosHeaderCell: CollectionViewCell<AudiosHeaderItemViewModel>
var label: UILabelPreferedWidth?
didSet
self.label?.textAlignment = .center
self.label?.numberOfLines = 0
self.label?.lineBreakMode = .byWordWrapping
self.label?.font = Font.Standard.size14
self.label?.textColor = UIColor(netHex: 0x185B97)
let labelLeftRightMargin = CGFloat(16)
override func setupViews()
self.backgroundColor = UIColor.white
self.label = UILabelPreferedWidth()
self.contentView.addSubview(self.label!)
override func setupConstraints()
self.label?.snp.makeConstraints (make) in
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 8, left: labelLeftRightMargin, bottom: 8, right: labelLeftRightMargin))
override func bindViewModel(viewModel: AudiosHeaderItemViewModel)
self.label?.text = viewModel.text
class UILabelPreferedWidth : UILabel
override var bounds: CGRect
didSet
print("SET BOUNDS", bounds)
if (bounds.size.width != oldValue.size.width)
self.setNeedsUpdateConstraints()
override func updateConstraints()
print("updateConstraints", preferredMaxLayoutWidth, bounds)
if(preferredMaxLayoutWidth != bounds.size.width)
preferredMaxLayoutWidth = bounds.size.width
super.updateConstraints()
我使用一种方法来计算单元格的大小,如下所示:
func sizeForCellWithViewModel(_ viewModel: IReusableViewModel, fittingSize: CGSize) -> CGSize
let cell = self.classRegistry.instances[viewModel.reuseIdentifier]!
(cell as! ICollectionViewCell).setViewModel(viewModel)
cell.translatesAutoresizingMaskIntoConstraints = false
cell.contentView.translatesAutoresizingMaskIntoConstraints = false
cell.frame = CGRect(x: 0, y: 0, width: fittingSize.width, height: fittingSize.height)
cell.setNeedsLayout()
cell.layoutIfNeeded()
print("SIZE FOR ", cell, "FITTING ", fittingSize, "IS", cell.systemLayoutSizeFitting(fittingSize))
return cell.systemLayoutSizeFitting(fittingSize)
它适用于具有一些图像和其他内容的多个单元格,但在缩放到 UILabel 内容这样简单的问题上却失败了。
我遇到的问题是systemLayoutSizeFitting.width
返回的大小大于我传递的fittingSize.width
参数。
我已经调试了很长时间,我发现preferredMaxLayoutWidth
没有正确更新,因为这个 UILabel 的边界超出了单元格框架 - 尽管我在那里使用了约束。
有人对此有好的解决方案吗?
我发现的唯一一个是在 CollectionViewCell 上使用它:
override var frame: CGRect
didSet
self.label?.preferredMaxLayoutWidth = self.frame.size.width - 32
但我讨厌它,因为它迫使我将其与约束同步,并且我的应用程序中的所有其他用例都需要记住复制它。 我正在寻找的是 AutoLayout,只有约束的解决方案。
【问题讨论】:
你使用了自动布局吗? 是的,通过 SnapKit,您可以在代码中看到 【参考方案1】:通过向 Cell 的 contentView 添加宽度约束解决了问题:
func sizeForCellWithViewModel(_ viewModel: IReusableViewModel, fittingSize: CGSize) -> CGSize
let cell = self.classRegistry.instances[viewModel.reuseIdentifier]!
(cell as! ICollectionViewCell).setViewModel(viewModel)
cell.contentView.frame = CGRect(x: 0, y: 0, width: fittingSize.width, height: fittingSize.height)
cell.contentView.snp.removeConstraints()
if fittingSize.width != 0
cell.contentView.snp.makeConstraints (make) in
make.width.lessThanOrEqualTo(fittingSize.width)
if fittingSize.height != 0
cell.contentView.snp.makeConstraints( (make) in
make.height.lessThanOrEqualTo(fittingSize.height)
)
cell.contentView.setNeedsLayout()
cell.contentView.layoutIfNeeded()
return cell.contentView.systemLayoutSizeFitting(fittingSize)
似乎这以某种方式使 UILabel 工作,并且 preferredWidth 不会发疯。
【讨论】:
以上是关于UILabel preferredMaxLayout 打破了自我调整大小的单元格的主要内容,如果未能解决你的问题,请参考以下文章
UIAlertController 或 UITextField 中的 UILabel 类似 UILabel
如何调整 UIView 的大小以获取大量 UILabel 并调整 UILabel 的大小以适合文本?