向上滚动时保持 UICollectionView 中的滚动位置

Posted

技术标签:

【中文标题】向上滚动时保持 UICollectionView 中的滚动位置【英文标题】:Maintain scroll position in UICollectionView when scrolling up 【发布时间】:2017-04-17 17:31:57 【问题描述】:

我有一个UICollectionView,带有类似聊天的视图 - 消息在底部显示最新消息。当用户向上滚动时,它会加载以前的消息并更新集合视图。我正在尝试在添加新数据时保持UICollectionView 的内容偏移量,但我无法让它工作。

这是我目前拥有的:

// First find the top most visible cell.
if let topCellIndexPath = collectionView.indexPathsForVisibleItems.sorted().first,
   let topCell = collectionView.cellForItem(at: topCellIndexPath),
   let topCellLayout = collectionView.layoutAttributesForItem(at: topCellIndexPath) 

    // Save the y position of the top cell.
    let previousTopCellY = topCellLayout.frame.origin.y

    // Perform updates on the UICollectionView without animation (ignore the fact it says adapter)
    adapter.performUpdates(animated: false)  [weak self] completed in
        if let strongSelf = self,
           let topCellNewIndexPath = strongSelf.collectionView.indexPath(for: topCell),
           let newTopCellLayout = strongSelf.collectionView.layoutAttributesForItem(at: topCellNewIndexPath) 

            // Calculate difference between the previous cell y value and the current cell y value
            let delta = previousTopCellY - newTopCellLayout.frame.origin.y

            // Add this to the collection view content offset
            strongSelf.collectionView.contentOffset.y += delta
        
    

这个好像不行,更新后有时候获取不到cell的indexPath。

编辑 根据@Arkku 的回答,这是可行的。虽然有轻微的闪烁。

let previousContentSize = collectionView.contentSize.height
adapter.performUpdates(animated: false)  [weak self] completed in
    if let strongSelf = self 
        let delta = strongSelf.collectionView.contentSize.height - previousContentSize
        strongSelf.collectionView.contentOffset.y += delta
    

【问题讨论】:

尝试从内容大小而不是单元格原点获取ˋdeltaˋ。 @Arkku 根据您的回答,用我的解决方案更新了问题。但是,有轻微的闪烁,并不完全平滑。我认为偏移量不是 100% 正确的...... 【参考方案1】:

正如我之前评论的那样,从contentSize 获取delta 可能比特定单元格的来源更好。基于您自己的版本的建议:

let previousContentHeight = collectionView.contentSize.height
adapter.performUpdates(animated: false)  [weak self] completed in
    guard let strongSelf = self else  return 
    let delta = strongSelf.collectionView.contentSize.height - previousContentHeight
    strongSelf.collectionView.bounds.origin.y += delta

【讨论】:

以上是关于向上滚动时保持 UICollectionView 中的滚动位置的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionview 的弹性标题视图并在向上滚动时最小化 UIImageView

当有人滚动到 UICollectionView 的顶部时,如何调用方法?

即使我们滚动,如何将部分标题保持在顶部:UICollectionView

除非用户向上滚动,否则保持溢出 div 滚动到底部

iPhone:滚动网页视图时需要保持键盘向上吗?

UICollectionView 在重新加载数据时滚动不平滑