gpt4 book ai didi

ios - UICollectionView 动画单元格越界

转载 作者:可可西里 更新时间:2023-11-01 03:31:33 24 4
gpt4 key购买 nike

我设置了一个具有以下设置的 UICollectionView:

  • collectionView 适合屏幕边界
  • 仅应用垂直滚动
  • 大部分单元格适合内容的宽度
  • 一些单元格可以在用户交互时动态改变它们的高度(动画)

它非常像 UITableView,在大多数情况下都可以正常工作,除了动画不适用的特定情况。

collectionView 中的堆叠单元格中,假设上面的单元格之一扩展了它的高度。那么下面的单元格必须向下移动以保持距离。如果此移动单元格的目标框架超出 collectionView 的 边界,则不会应用任何动画并且单元格会消失。

相反的情况以同样的方式工作;如果下部单元格的源帧超出屏幕边界(当前在边界之外)并且上部单元格应该收缩,则不会应用任何动画,它只会出现在目标帧上。

这在 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])
}

在那种情况下,我遇到了这样的动画:

bug

如何解决?

我认为您可以尝试调整 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
}

避免在布局失效时错误的目标内容偏移量计算。

fix

关于ios - UICollectionView 动画单元格越界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40711925/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com