当我创建我的集合视图时,我将单元格定义为具有相同布局的单元格
class FriendsController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
fileprivate let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Recent"
collectionView?.backgroundColor = UIColor.white
collectionView?.register(FriendCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.alwaysBounceVertical = true
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: 100)
}
}
class FriendCell: BaseCell {
override func setupViews() {
addSubview(profileImageView)
addSubview(dividerLineView)
profileImageView.image = UIImage(named: "zuckprofile")
setupContainerView()
addConstraintsWithFormat( "H:|-12-[v0(68)]|", views: profileImageView)
addConstraintsWithFormat( "V:[v0(68)]", views: profileImageView)
addConstraint(NSLayoutConstraint(item: profileImageView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
addConstraintsWithFormat( "H:|-82-[v0]|", views: dividerLineView)
addConstraintsWithFormat( "V:[v0(1)]|", views: dividerLineView)
}
func setupContainerView() {
let containerView = UIView()
addSubview(containerView)
addConstraintsWithFormat("H:|-90-[v0]|", views: containerView)
addConstraintsWithFormat( "V:[v0(50)]", views: containerView)
addConstraint(NSLayoutConstraint(item: containerView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))
containerView.addSubview(nameLabel)
containerView.addSubview(messageLabel)
containerView.addSubview(timelabel)
containerView.addConstraintsWithFormat( "H:|[v0][v1]|", views: nameLabel, timelabel )
containerView.addConstraintsWithFormat( "V:|[v0][v1(24)]|", views: nameLabel, messageLabel)
containerView.addConstraintsWithFormat( "H:|[v0]-12-|", views: messageLabel )
containerView.addConstraintsWithFormat("V:|[v0(20)]|", views: timelabel)
}
}
extension UIView {
func addConstraintsWithFormat(_ format: String , views: UIView...) {
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerated() {
let key = "v\(index)"
viewsDictionary[key] = view
view.translatesAutoresizingMaskIntoConstraints = false
}
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
}
}
因此,从代码看来,单元格中的所有内容都是相同的。具有相同的布局,约束等 然后我得到了这个可怕的结果。
也许有人知道 为什么 这种行为发生在这里?
答案 0 :(得分:1)
我认为问题在于nameLabel
和timeLabel
内在大小及其内容拥抱优先级和内容压缩阻力优先级之间的歧义(检查this article)。
您有两个选项,可以设置setupContainerView
中的两个标签的水平抗压力和拥抱优先级:
nameLabel.setContentHuggingPriority(UILayoutPriority.defaultLow, for: .horizontal)
nameLabel.setContentCompressionResistancePriority(UILayoutPriority.defaultLow, for: .horizontal)
timeLabel.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .horizontal)
timeLabel.setContentCompressionResistancePriority(UILayoutPriority.defaultHigh, for: .horizontal)
这将使timeLabel
根据其内容保持大小,而nameLabel
将采用其余内容(意味着如果未设置时间,timeLabel
将缩小为宽度0,其余的将被nameLabel
)占用。
或者为其中一个标签设置显式宽度,例如:
timeLabel.widthAnchor.constraint(equalToConstant: 40).isActive = true
修改强>
根据Apple docs,
如果在运行时出现模糊布局,Auto Layout会选择一种可能的解决方案。这意味着布局可能会或可能不会按预期显示。此外,没有警告写入控制台,也没有办法为不明确的布局设置断点。
当拉伸一系列视图以填充空格时,如果所有视图具有相同的内容拥抱优先级,则布局不明确。自动布局不知道应该拉伸哪个视图。
我找不到的文档告诉我们,自动布局如何解决这个问题 - 我相信原因是要确保我们不依赖于此而是明确地设置优先级。因此,任何随机算法都可以真正选择拉伸的标签(甚至是拉伸的尺寸)。根据您的结果,我们最多可以得出结论,可能不是基于标签作为子视图添加的顺序。