自定义 CollectionView 布局重新加载数据不起作用
Posted
技术标签:
【中文标题】自定义 CollectionView 布局重新加载数据不起作用【英文标题】:Custom CollectionView Layout Reload Data not working 【发布时间】:2019-01-09 18:46:44 【问题描述】:在创建自定义集合视图布局时,reloadData 不起作用
在创建自定义集合视图布局时,在我进行无限滚动并从 api 调用新数据后,reloadData 不起作用
我怀疑这是因为从 collectionview 调用的固定项目。我将如何更新它?
protocol CustomCollectionViewLayoutDelegate: class
func collectionView(
collectionView: UICollectionView,
heightForItemAtIndexPath indexPath: IndexPath
) -> CGFloat
public class CustomCollectionViewLayout: UICollectionViewLayout
weak var delegate: CustomCollectionViewLayoutDelegate!
public var numberOfColumns: Int = 1
private var cache: [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
private var contentHeight: CGFloat = 0
private var contentWidth: CGFloat
guard let collectionView = collectionView else
return 0
let insets = collectionView.contentInset
return collectionView.bounds.width - (insets.left + insets.right)
public override var collectionViewContentSize: CGSize
return CGSize(
width: self.contentWidth,
height: self.contentHeight
)
public override func prepare()
if cache.isEmpty
let columnWidth: CGFloat = self.contentWidth / CGFloat(self.numberOfColumns)
var xOffset: [CGFloat] = [CGFloat]()
for column in 0...numberOfColumns
xOffset.append(CGFloat(column) * columnWidth)
var yOffset: [CGFloat] = [CGFloat](repeating: 0, count: self.numberOfColumns)
var column: Int = 0
for item in 0 ..< collectionView!.numberOfItems(inSection: 0)
// for item in 0 ..< collectionView!.numberOfItems(inSection: 0)
let indexPath: IndexPath = IndexPath(item: item, section: 0)
let height = delegate.collectionView(
collectionView: collectionView!,
heightForItemAtIndexPath: indexPath
)
let frame: CGRect = CGRect(
x: xOffset[column],
y: yOffset[column],
width: columnWidth,
height: height
)
let attributes: UICollectionViewLayoutAttributes = UICollectionViewLayoutAttributes(
forCellWith: indexPath
)
attributes.frame = frame
self.cache.append(attributes)
self.contentHeight = max(contentHeight, frame.maxY)
yOffset[column] = yOffset[column] + height
column = column < (self.numberOfColumns - 1) ? (column + 1) : 0
public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
var visibleLayoutAttributes = [UICollectionViewLayoutAttributes]()
// Loop through the cache and look for items in the rect
for attributes in cache
if attributes.frame.intersects(rect)
visibleLayoutAttributes.append(attributes)
return visibleLayoutAttributes
public override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
return cache[indexPath.item]
我只需要能够使用 reloadData 来更新我的无限滚动数据
【问题讨论】:
【参考方案1】:我建议将此功能添加到您的 CustomCollectionViewLayout
func reloadData()
self.cache = [UICollectionViewLayoutAttributes]()
然后当你想重新加载你的数据时
if let layout = self.collectionView.collectionViewLayout as? CustomCollectionViewLayout
layout.reloadData()
collectionView.reloadData()
删除 if cache.isEmpty 可能会导致您的布局重用
【讨论】:
【参考方案2】:只要删除if cache.isEmpty
就可以了
【讨论】:
【参考方案3】:如果您删除缓存,现有项目的布局也会发生变化,这会造成糟糕的用户体验。当用户向下滚动视图时,他/她会注意到现有项目突然发生了变化。
prepare()
方法在您调用.reloadData
时触发,您应该在此方法中处理追加新元素。目前,它不会更新布局,因为缓存不是零。 您应该比较缓存中的项目数和collectionView,而不是删除缓存中的元素。
查看以下示例实现的答案;
https://***.com/a/70154474/13754736
【讨论】:
以上是关于自定义 CollectionView 布局重新加载数据不起作用的主要内容,如果未能解决你的问题,请参考以下文章
在我的自定义 collectionView 布局中未调用 prepare()
使用自定义 collectionView 布局更改单元格大小时如何使用 ScrollToItem(at:)
使用UICollectionView自定义样式01-水平线性布局
使用自定义布局重新加载 UICollectionView 会引发错误