Swift5中如何在滚动时仅放大UICollectionView首个单元格
解决方案
你的问题根源在于代码错误地将当前可见区域的第一个单元格标记为放大对象,而不是你真正需要的列表的首个单元格(indexPath.row = 0)。同时,滚动时频繁调用reloadData()会严重影响性能,需要一并优化。
修正后的基础方案
直接移除跟踪可见单元格的逻辑,在布局方法中仅针对列表首个单元格设置放大尺寸:
// 删除原有的firstVisibleCell变量和UIScrollViewDelegate扩展(不再需要) extension someCollectionView: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { // 仅给列表第一个单元格设置放大尺寸 if indexPath.row == 0 { return CGSize(width: self.bounds.width * 0.9, height: 120) } // 其他单元格使用正常尺寸 return CGSize(width: self.bounds.width * 0.85, height: 120) } }
进阶优化方案(按需选择)
如果你的需求是仅当首个单元格在可见区域时才放大它,滚出屏幕后所有单元格恢复正常尺寸,可以使用以下方案避免全量刷新,提升性能:
private var isFirstCellVisible = false extension someCollectionView: UIScrollViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { let firstCellIndex = IndexPath(row: 0, section: 0) let currentVisibleState = indexPathsForVisibleItems.contains(firstCellIndex) // 仅当首个单元格的可见状态变化时,才刷新该单元格 if currentVisibleState != isFirstCellVisible { isFirstCellVisible = currentVisibleState reloadItems(at: [firstCellIndex]) } } } extension someCollectionView: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { if indexPath.row == 0 && isFirstCellVisible { return CGSize(width: self.bounds.width * 0.9, height: 120) } return CGSize(width: self.bounds.width * 0.85, height: 120) } }
原代码失效原因
原代码中visibleCells.first返回的是当前屏幕上最顶部的可见单元格,当你滚动到列表末尾时,如果最后一个单元格成为屏幕最顶部的可见元素(比如CollectionView高度刚好只能容纳一个单元格),就会错误地将它标记为放大对象。而直接针对indexPath.row = 0判断,就能确保只有列表的首个单元格被放大。
内容的提问来源于stack exchange,提问作者Gucci
相关产品推荐
相关产品推荐

