Ios 为什么collectionView单元格的布局应该是相同的,但却存在差异?
创建集合视图时,我将单元格定义为具有相同布局的相同单元格Ios 为什么collectionView单元格的布局应该是相同的,但却存在差异?,ios,uicollectionview,autolayout,uicollectionviewlayout,Ios,Uicollectionview,Autolayout,Uicollectionviewlayout,创建集合视图时,我将单元格定义为具有相同布局的相同单元格 class FriendsController: UICollectionViewController, UICollectionViewDelegateFlowLayout { fileprivate let cellId = "cellId" override func viewDidLoad() { super.viewDidLoad() navigationItem.title =
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))
}
}
因此,从代码中可以看出,单元格中的所有内容都是相同的。具有相同的布局、约束等
然后我得到了这个可怕的结果
也许有人知道为什么在这里发生这种行为?我相信问题在于
名称标签
和时间标签
固有大小及其内容拥抱优先级和内容压缩阻力优先级之间的不确定性(检查)
您有两个选项,在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)
这将使时间标签
根据其内容保持大小,而名称标签
将占据其余内容(这意味着如果未设置时间,则时间标签
将缩小到宽度0,其余内容将被名称标签
占据)
或为其中一个标签设置显式宽度,例如:
timeLabel.widthAnchor.constraint(equalToConstant: 40).isActive = true
编辑
根据,
当运行时出现不明确的布局时,自动布局会选择一种可能的解决方案来使用。这意味着布局可能会出现,也可能不会出现预期的效果。此外,没有向控制台写入警告,也没有办法为不明确的布局设置断点
或:
拉伸一系列视图以填充空间时,如果所有视图都具有相同的内容包含优先级,则布局不明确。自动布局不知道应该拉伸哪个视图
我所能找到的所有文档都没有告诉我们,自动布局是如何解决这些问题的——我相信原因是为了确保我们不会依赖于此,而是明确地设置优先级。因此,被拉伸的标签(甚至拉伸到的大小)实际上可以由任何随机算法选择。根据你的结果,我们最多只能得出结论,这可能不是基于标签作为子视图添加的顺序。你能展示一下你期望它们的样子吗?我希望看到所有单元格中的绿色和棕色条带大小相同。如果问题是模糊性,那么为什么它的布局不同?在单元格数组中只有一个单元格,而其余单元格的布局不同同样的概念?无论单元布局中存在什么样的模糊性,它们都应该是相同的吗?@N.Khasanov我希望如此,但在模糊的情况下,行为是未定义的,所以我想这可能会发生。试着使用我的建议,如果这有帮助的话,我们至少可以确定这是根本原因。你写的所有东西都是有效的。但是无论如何(如果我能知道内部默认规则,即更倾向于使用这种或那种特定的方式来表示视图。因为当我使用两个UILabel并添加诸如“H |[v0][v1]|之类的约束时,我在视觉格式语言中对默认内部内容的优先权有着“相同”的痛苦)因此,系统倾向于一个标签高于另一个标签(但当我只添加最小的澄清非本质细节,如“H |-[v0][v1]|或“H |[v0][v1]-|”时,系统使两个标签的内容包含优先级参数相同simultaneously@N.Khasanov您永远不应该依赖自动布局的内部工作,这就是为什么它是内部的(见我的最新答案)我们非常小心,不要透露任何关于autolayout如何解决这种模糊性的信息——这些文档明确地告诉我们始终要明确地设置优先级。我必须说——如果我实现了这一点,我会使用
arc4random
来选择要真正随机打破的约束,这样库用户将被迫遵守我的医生。看来你是对的。非常感谢你,你帮了我很多