UICollectionView流式布局未正确包装单元格

79
我有一个带有FlowLayout的UICollectionView。大部分时间它都能正常工作,但是偶尔会出现一个单元格无法正确换行的情况。例如,在第三行的第一列应该出现的单元格实际上却在第二行后面,并且空着的地方应该是它的位置(如下图所示)。你只能看到这个单元格的左侧(其余部分被剪切了),并且应该出现的位置为空白。

这种情况不是总是发生;每次发生的行数都不同。一旦出现这种情况,我可以向上滚动,然后再返回,此时单元格就会自动修复。或者,当我点击该单元格(通过推送进入下一个视图)然后再按“返回”键时,我会看到该单元格处于错误位置,然后它会跳转到正确的位置。

滚动速度似乎会使问题更容易重现。当我慢慢滚动时,偶尔仍然能看到单元格在错误位置,但随即它就会立即跳回正确位置。

问题始于我添加了段落插入。以前,我的单元格几乎贴在集合边界上(很少或没有插入),我没有注意到问题。但这意味着集合视图的左右两侧是空的。即,无法滚动。另外,滚动条没有靠在右边。

我可以在模拟器和iPad 3上重现此问题。

我想问题是由于左右段落插入引起的...但如果值是错误的,那么我期望行为应该是一致的。我不知道这是否可能是Apple的一个错误?或者这可能是由于插入或类似的东西累计而导致的。

Illustration of problem and settings

跟进:我已经使用Nick在下面提供的答案两年多了,没有任何问题(如果有人想知道那个答案是否存在漏洞 - 我还没有发现)。干得好,Nick。

12个回答

0

这可能有点晚了,但请确保在可能的情况下在prepare()中设置您的属性。

我的问题是单元格正在布局,然后在layoutAttributesForElements中进行更新。当新单元格进入视图时,这会导致闪烁效果。

通过将所有属性逻辑移动到prepare中,然后在UICollectionViewCell.apply()中设置它们,消除了闪烁并创建了更流畅的单元格显示。


-1

Nick Snyder的答案的Swift 5版本:

class NDCollectionViewFlowLayout: UICollectionViewFlowLayout {
    open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect)
        var newAttributes = [AnyHashable](repeating: 0, count: attributes?.count ?? 0)
        for attribute in attributes ?? [] {
            if (attribute.frame.origin.x + attribute.frame.size.width <= collectionViewContentSize.width) && (attribute.frame.origin.y + attribute.frame.size.height <= collectionViewContentSize.height) {
                newAttributes.append(attribute)
            }
        }
        return newAttributes as? [UICollectionViewLayoutAttributes]
    }
}

或者您可以使用UICollectionViewFlowLayout的扩展:

extension UICollectionViewFlowLayout {
    open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect)
        var newAttributes = [AnyHashable](repeating: 0, count: attributes?.count ?? 0)
        for attribute in attributes ?? [] {
            if (attribute.frame.origin.x + attribute.frame.size.width <= collectionViewContentSize.width) && (attribute.frame.origin.y + attribute.frame.size.height <= collectionViewContentSize.height) {
                newAttributes.append(attribute)
            }
        }
        return newAttributes as? [UICollectionViewLayoutAttributes]
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接