为什么collectionView单元格的布局应该是相同的?

时间:2018-01-16 11:28:16

标签: ios uicollectionview autolayout uicollectionviewlayout

当我创建我的集合视图时,我将单元格定义为具有相同布局的单元格

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))
    }
}

因此,从代码看来,单元格中的所有内容都是相同的。具有相同的布局,约束等 然后我得到了这个可怕的结果。enter image description here

也许有人知道 为什么 这种行为发生在这里?

1 个答案:

答案 0 :(得分:1)

我认为问题在于nameLabeltimeLabel内在大小及其内容拥抱优先级和内容压缩阻力优先级之间的歧义(检查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会选择一种可能的解决方案。这意味着布局可能会或可能不会按预期显示。此外,没有警告写入控制台,也没有办法为不明确的布局设置断点。

other doc

  

当拉伸一系列视图以填充空格时,如果所有视图具有相同的内容拥抱优先级,则布局不明确。自动布局不知道应该拉伸哪个视图。

我找不到的文档告诉我们,自动布局如何解决这个问题 - 我相信原因是要确保我们不依赖于此而是明确地设置优先级。因此,任何随机算法都可以真正选择拉伸的标签(甚至是拉伸的尺寸)。根据您的结果,我们最多可以得出结论,可能不是基于标签作为子视图添加的顺序。