UICollectionView 不遵守 UICollectionViewLayoutAttributes 的 zIndex
UICollectionView not obeying zIndex of UICollectionViewLayoutAttributes
我想要达到的效果是一种粘性 header 单元格。粘性细胞漂浮在其他细胞之上对我来说很重要。有点像这样:
┌──────────┐
│ │
│ Cell 0 │
│ ├┐
└┬─────────┘│
│ Cell 4 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 5 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 6 │
│ │
└──────────┘
单元格 4、5 和 6 通常是可见的,我在 layoutAttributesForElementsInRect:
期间在我的 UICollectionViewFlowLayout
子类中构建单元格 0 的属性。我所做的就是调用超级实现,确定我需要添加的单元格,然后构造 UICollectionViewLayoutAttributes(forCellWithIndexPath:)
。然后我将它的 zIndex
设置为 1
(默认为 0
)。
我遇到的问题是 UICollectionView
似乎总是忽略 zIndex
┌──────────┐
│ │
│ Cell 0 │
│┌─────────┴┐
└┤ │
│ Cell 4 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 5 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 6 │
│ │
└──────────┘
现在我相信可以使用 3d 变换从视觉上解决这个问题,但这对我不起作用,因为我不希望任何点击进入顶部的单元格。因此,在此示例中,我不希望 Cell 4 接收用于 Cell 0 的抽头。
有人有什么想法吗?这是在 iOS 8.4.
我做了一个独立的项目来去除我所有无关的代码。在这个过程中我想我找到了自己的解决方案。
override func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
和
override func finalLayoutAttributesForDisappearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
我们也没有应用新的 zIndex
所以我认为这是造成它的原因。
只是觉得我应该 post 支持解决方案,以防万一在搜索其他人时出现这种情况。
在 UICollectionViewLayout 中设置 zIndex 对我不起作用
我在 UICollectionViewController 的方法中设置了 zIndex
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
customCell.layer.zPosition = 0;
}
我最好的猜测是布局和控制器将 zIndex 设置为奇怪的东西
您需要同时设置这两个值。
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
}
}
由于 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
}
我在 UICollectionViewLayout
的子类中遇到了类似的问题,其中单元格的记录不考虑对 UICollectionViewLayoutAttributes.zIndex
的更新,但我能够通过重新加载移动的单元格来解决该问题。
我特别用了这个:
collectionView.performBatchUpdates({
collectionView.moveItem(at:indexPath, to:newIndexPath)
})
collectionView.reloadItems(at: [indexPath, newIndexPath])
似乎这种情况仍在 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)
}
我想要达到的效果是一种粘性 header 单元格。粘性细胞漂浮在其他细胞之上对我来说很重要。有点像这样:
┌──────────┐
│ │
│ Cell 0 │
│ ├┐
└┬─────────┘│
│ Cell 4 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 5 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 6 │
│ │
└──────────┘
单元格 4、5 和 6 通常是可见的,我在 layoutAttributesForElementsInRect:
期间在我的 UICollectionViewFlowLayout
子类中构建单元格 0 的属性。我所做的就是调用超级实现,确定我需要添加的单元格,然后构造 UICollectionViewLayoutAttributes(forCellWithIndexPath:)
。然后我将它的 zIndex
设置为 1
(默认为 0
)。
我遇到的问题是 UICollectionView
似乎总是忽略 zIndex
┌──────────┐
│ │
│ Cell 0 │
│┌─────────┴┐
└┤ │
│ Cell 4 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 5 │
│ │
└──────────┘
┌──────────┐
│ │
│ Cell 6 │
│ │
└──────────┘
现在我相信可以使用 3d 变换从视觉上解决这个问题,但这对我不起作用,因为我不希望任何点击进入顶部的单元格。因此,在此示例中,我不希望 Cell 4 接收用于 Cell 0 的抽头。
有人有什么想法吗?这是在 iOS 8.4.
我做了一个独立的项目来去除我所有无关的代码。在这个过程中我想我找到了自己的解决方案。
override func initialLayoutAttributesForAppearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
和
override func finalLayoutAttributesForDisappearingItemAtIndexPath(itemIndexPath: NSIndexPath) -> UICollectionViewLayoutAttributes?
我们也没有应用新的 zIndex
所以我认为这是造成它的原因。
只是觉得我应该 post 支持解决方案,以防万一在搜索其他人时出现这种情况。
在 UICollectionViewLayout 中设置 zIndex 对我不起作用
我在 UICollectionViewController 的方法中设置了 zIndex
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
customCell.layer.zPosition = 0;
}
我最好的猜测是布局和控制器将 zIndex 设置为奇怪的东西
您需要同时设置这两个值。 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
}
}
由于 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
}
我在 UICollectionViewLayout
的子类中遇到了类似的问题,其中单元格的记录不考虑对 UICollectionViewLayoutAttributes.zIndex
的更新,但我能够通过重新加载移动的单元格来解决该问题。
我特别用了这个:
collectionView.performBatchUpdates({
collectionView.moveItem(at:indexPath, to:newIndexPath)
})
collectionView.reloadItems(at: [indexPath, newIndexPath])
似乎这种情况仍在 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)
}