UICollectionView不服从UICollectionViewLayoutAttributes的zIndex

时间:2015-07-29 10:15:45

标签: ios uikit uicollectionview uicollectionviewcell

我想要实现的效果是一种粘性标题单元格。对我来说,粘性细胞漂浮在其他细胞的顶部是很重要的。有点像这样:

┌──────────┐ 
│          │ 
│  Cell 0  │ 
│          ├┐
└┬─────────┘│
 │  Cell 4  │
 │          │
 └──────────┘
 ┌──────────┐
 │          │
 │  Cell 5  │
 │          │
 └──────────┘
 ┌──────────┐
 │          │
 │  Cell 6  │
 │          │
 └──────────┘

单元格4,5和6通常是可见的,我在UICollectionViewFlowLayout期间在layoutAttributesForElementsInRect:子类中构建单元格0的属性。我所做的只是调用超级实现,确定我需要添加哪个单元格然后构造UICollectionViewLayoutAttributes(forCellWithIndexPath:)。然后,我将zIndex设置为1(默认为0)。

我遇到的问题是UICollectionView似乎总是忽略zIndex

┌──────────┐ 
│          │ 
│  Cell 0  │ 
│┌─────────┴┐
└┤          │
 │  Cell 4  │
 │          │
 └──────────┘
 ┌──────────┐
 │          │
 │  Cell 5  │
 │          │
 └──────────┘
 ┌──────────┐
 │          │
 │  Cell 6  │
 │          │
 └──────────┘

现在我相信可以使用3D变换在视觉上对其进行排序,但这对我不起作用,因为我不希望任何点击进入顶部的单元格。所以在这个例子中,我不希望Cell 4接收用于Cell 0的抽头。

有没有人有任何想法?这是在iOS 8.4上。

6 个答案:

答案 0 :(得分:5)

在UICollectionViewLayout中设置zIndex并不适合我

我在UICollectionViewController方法中设置了zIndex

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
customCell.layer.zPosition = 0;
}

我最好的猜测是布局和控制器之间的东西将zIndex设置为奇怪的东西

答案 1 :(得分:3)

我创建了一个独立的项目,以便删除所有无关的代码。在这个过程中,我认为我找到了自己的解决方案。

override func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?

override func finalLayoutAttributesForDisappearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?

还没有应用新的zIndex所以我认为这是导致它的原因。

我想应该回复一下这个解决方案,以防其他人搜索到它。

答案 2 :(得分:2)

由于UIKit错误,无法更新UICollectionViewLayoutAttributes.zIndex

此代码可以解决问题:

// In your UICollectionViewCell subclass:
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
    super.apply(layoutAttributes)
    layer.zPosition = CGFloat(layoutAttributes.zIndex) // or any zIndex you want to set
}

答案 3 :(得分:0)

您需要设置两个值。 zIndex 3DTransform 参数。

class HeaderUnderCellsLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let attributesArray = super.layoutAttributesForElements(in: rect) else { return nil }

        attributesArray.forEach { attributes in
            if attributes.representedElementCategory == .supplementaryView && attributes.representedElementKind == UICollectionView.elementKindSectionHeader {
                attributes.transform3D = CATransform3DMakeTranslation(0, 0, -10)
                attributes.zIndex = -200
            }
        }
        return attributesArray
    }

    override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attributes = super.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath)
        attributes?.transform3D = CATransform3DMakeTranslation(0, 0, -10)
        attributes?.zIndex = -200
        return attributes
    }
}

答案 4 :(得分:0)

我在UICollectionViewLayout的子类中遇到了类似的问题,其中记录单元格不考虑对UICollectionViewLayoutAttributes.zIndex的更新,但是我可以通过重新加载移动的单元格来解决此问题。

我特别使用了这个:

    collectionView.performBatchUpdates({
        collectionView.moveItem(at:indexPath, to:newIndexPath)
    })

    collectionView.reloadItems(at: [indexPath, newIndexPath])

答案 5 :(得分:0)

在iOS 14上似乎仍在发生这种情况。这是我设法解决的情况:

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
    {
        guard let attributes = collectionView.collectionViewLayout.layoutAttributesForItem(at: indexPath) else
        {
            assert(false)
            return
        }
        cell.layer.zPosition = CGFloat(attributes.zIndex)
    }
    func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath)
    {
        guard let attributes = collectionView.collectionViewLayout.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath) else
        {
            assert(false)
            return
        }
        view.layer.zPosition = CGFloat(attributes.zIndex)
    }