swift - 根据条件添加约束的奇怪行为

标签 swift constraints uicollectionviewcell

我正在为两个人之间的对话创建 View 。我将 UICollectionView 与自定义单元格一起使用,并使用一个标志,根据该标志我决定消息应该向左还是向右对齐。如果我仅使用单个对齐方向,则约束可以正常工作,甚至可以在基于条件的对齐情况下正常工作,除非 UICollectionView 中的消息数量少于四。所以我知道约束并没有错。但是,一旦我添加第四条消息,先前单元格内容和单元格的对齐和顺序就会受到干扰。随附的屏幕截图显示了问题。

correct behaviour with 3 or less messages

wrong behaviour when 4 or more messages added

var avatarHorizontal = NSLayoutConstraint(item: messageCell.avatarImageView,
                                                      attribute: .leading,
                                                      relatedBy: .equal,
                                                      toItem: cell,
                                                      attribute: .leading,
                                                      multiplier: 1,
                                                      constant: 7)
var messageTextContainerHorizontal = NSLayoutConstraint(item: messageCell.messageTextContainer,
                                                                    attribute: .leading,
                                                                    relatedBy: .equal,
                                                                    toItem: messageCell.avatarImageView,
                                                                    attribute: .trailing,
                                                                    multiplier: 1,
                                                                    constant: 10)

if isCellFromUser {
    avatarHorizontal = NSLayoutConstraint(item: messageCell.avatarImageView,
                                                       attribute: .trailing,
                                                       relatedBy: .equal,
                                                       toItem: cell,
                                                       attribute: .trailing,
                                                       multiplier: 1,
                                                       constant: -16)
    messageTextContainerHorizontal = NSLayoutConstraint(item: messageCell.messageTextContainer,
                                                                     attribute: .trailing,
                                                                     relatedBy: .equal,
                                                                     toItem: messageCell.avatarImageView,
                                                                     attribute: .leading,
                                                                     multiplier: 1,
                                                                     constant: -10)
}

更新1: 我已经尝试过 @Sh_Khan 的建议,但这从 Collection View 的第一个单元格开始出现问题。

我什至尝试了以下代码,它保留了我之前遇到的原始形式的问题:

if isCellFromUser {
    cell?.addConstraints([avatarRightAligned, messageTextContainerRightAligned])
} else {
    cell?.addConstraints([avatarLeftAligned, messageTextContainerLeftAligned])
}

所以我注意到一个趋势,只要我引入 if/else 语句,无论我重用引用变量来条件分配约束对象还是有条件地添加约束,都会出现问题(已为约束对象声明了单独的引用变量)。

更新2: 所以事实证明,我必须在 init 方法中添加所有约束,而不是在 cellForRowAt 方法中添加,然后激活和取消激活 cellForRowAt< 中的相关约束。感谢@Sh_Khan 的捕捉并提供了解决方案。现在,出现了另一个问题,那就是我必须根据完全相同的条件更改背景和前景色,那么这个问题的解决方案是什么?

更新3: 我为 更新 2 here 中描述的问题添加了一个单独的问题

最佳答案

It even works correctly with condition based alignment unless number of messages in UICollectionView is less than four.

这种情况发生在集合单元格出队时,因此当第四个单元格出现时,它可能具有左/右约束对齐,并且您的代码尝试给它相反的对齐方式,因此会发生冲突

您可以做的是创建 2 个约束并将它们设置在 init

var leftCon,rightCon:NSLayoutConstraint!

然后根据cellForRowAt内的消息对齐来使用它们

leftCon.isActive = isLeftAligned
rightCon.isActive = !isLeftAligned

关于swift - 根据条件添加约束的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56600351/

相关文章:

ios - 无法在 Xcode 中为启动屏幕设置自动布局约束

ios - 如何使用 SDWebImage 调整下载的图像大小?

ios - 使用 UICollectionView header 中的按钮进行操作

swift - C-Style i++ for 在 swift 问题中被弃用

ios - 页面 View Controller 不显示点

iOS 11 错误,didselectrowatindexpath 调用同时用两根手指点击单元格

ios - 快速将单元格并排放置在 Collection View 中

ios - ARKit + SceneKit : Object lags when adding to the scene

具有类型构造函数的类型类定义的 Haskell 实例

ios - 重新定位 uilabel