2017-04-17 12 views
0

UICollectionViewにはチャットのようなチャットがあります。メッセージは最下部に最新のものが表示されます。ユーザーがスクロールすると、以前のメッセージがロードされ、コレクションビューが更新されます。私は新しいデータが追加されると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 
     } 
    } 
} 

これが動作するようには思えない、と時々更新後の細胞のindexPathを取得することはできません。

EDIT @ 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 
    } 
} 
+0

セル起源ではなくコンテンツサイズから試着してみてください。 – Arkku

+0

@Arkkuそれはあなたの答えに基づいて私の解決策で質問を更新しました。しかし、わずかなちらつきがあり、完全に滑らかではありません。オフセットは100%正しいわけではないと思います... – Tometoyou

答えて

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 
} 
関連する問題