UICollectionView超出边界的动画单元格
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UICollectionView超出边界的动画单元格相关的知识,希望对你有一定的参考价值。
我设置了一个具有以下设置的UICollectionView
:
- collectionView适合屏幕边界
- 仅应用垂直滚动
- 大多数单元格适合内容的宽度
- 一些单元格可以动态地改变用户交互的高度(动画)
它非常像UITableView
,在大多数情况下都能正常工作,除非动画不适用时有一种特殊情况。
在collectionView
的堆积细胞中,据说其中一个上部细胞扩大了它的高度。然后下部单元必须向下移动以保持距离。如果此移动单元格的目标帧超出collectionView's
界限,则不应用动画并且单元格消失。
相反的情况也是如此;如果下部单元格的源帧超出屏幕边界(当前在边界之外)并且上部单元格应该缩小,则不应用动画,它只会出现在目标帧上。
这在由UICollectionView
控制的内存管理逻辑中似乎是合适的,但同时向用户显示某些内容只是出现或消失的蓝色并不自然。我用UITableView对此进行了测试,同样的事情发生了。
这个问题有解决方法吗?
您应该添加一些代码或至少是您的UI问题的GIF。
我尝试使用基本的UICollectionViewLayout
子类复制您的问题:
protocol CollectionViewLayoutDelegate: AnyObject {
func heightForItem(at indexPath: IndexPath) -> CGFloat
}
class CollectionViewLayout: UICollectionViewLayout {
weak var delegate: CollectionViewLayoutDelegate?
private var itemAttributes: [UICollectionViewLayoutAttributes] = []
override func prepare() {
super.prepare()
itemAttributes = generateItemAttributes()
}
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
return collectionView?.contentOffset ?? .zero
return super.targetContentOffset(forProposedContentOffset: proposedContentOffset)
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return itemAttributes.first { $0.indexPath == indexPath }
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return itemAttributes.filter { $0.frame.intersects(rect) }
}
private func generateItemAttributes() -> [UICollectionViewLayoutAttributes] {
var offset: CGFloat = 0
return (0..<numberOfItems()).map { index in
let indexPath = IndexPath(item: index, section: 0)
let frame = CGRect(
x: 0,
y: offset,
width: collectionView?.bounds.width ?? 0,
height: delegate?.heightForItem(at: indexPath) ?? 0
)
offset = frame.maxY
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = frame
return attributes
}
}
}
在一个简单的UIViewController
中,每次选择一个单元格时我都会重新加载第一个单元格:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
updatedIndexPath = IndexPath(item: 0, section: 0)
collectionView.reloadItems(at: [updatedIndexPath])
}
在那种情况下,我遇到了这样的动画:
How to fix it ?
我想你可以试着调整super.finalLayoutAttributesForDisappearingItem(at: itemIndexPath)
返回的属性来计算它的正确帧并使用z-index。
但您也可以尝试使所有布局无效,如下所示:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
layout = CollectionViewLayout()
layout.delegate = self
collectionView.setCollectionViewLayout(layout, animated: true)
}
并覆盖:
override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {
return collectionView?.contentOffset ?? .zero
}
在布局无效时避免错误的目标内容偏移计算。
以上是关于UICollectionView超出边界的动画单元格的主要内容,如果未能解决你的问题,请参考以下文章
UICollectionView 单元格布局超出了集合视图的范围
表格视图单元格中的 uicollectionview 出现错误:索引超出范围,为啥?
当边界 UICollectionView 更改时调整单元格大小