airbnb / MagazineLayout

A collection view layout capable of laying out views in vertically scrolling grids and lists.
Apache License 2.0
3.3k stars 219 forks source link

Reloading collectionview does not maintain content offset #56

Open ChengmingLu opened 5 years ago

ChengmingLu commented 5 years ago

Describe the bug When reloadData() is called, the collectionView sometimes doesn't preserve the scrolling position, causing the collectionView to jump abruptly

To Reproduce Steps to reproduce the behavior:

  1. Open and run the stock example project (workspacce) under MagazineLayoutExample
  2. Please see the attached gif to reproduce this issue Note: this doesn't occur every time, you need to adjust scrolling position before reloading the data if you cannot reproduce it at the beginning

Expected behavior The screen should maintain its position after reloading data

Screenshots

Untitled

Smartphone (please complete the following information):

Additional context Not sure if this could be a bug in UICollectionView rather than MagazineLayout, please advise.

Sparrow-Iv commented 4 years ago

The problem is still relevant, is there any solution?

eliotwjohnson commented 4 years ago

We're experiencing this issue as well. Any time a reload occurs when the collection view is scrolled, its contentSize and contentOffset change, resulting in the jump. @bryankeller are there any known workarounds for this?

acecilia commented 4 years ago

Maybe related:

ghost commented 4 years ago

I am also experiencing this issue. Whenever a reload happens, when the collection view is scrolled, its contentOffset change, resulting in the jump. @bryankeller is there any known fix/solution for the same?

ghost commented 4 years ago

Seems like once we scroll the view and then on reload of data content size of collection view is not same as before even though data is same. Self sizing return different content size each time. I also looked into the item size returned in method preferredLayoutAttributesFitting which is same for items before and after reload of data.

@bryankeller does any one looking into this issue?

maxcox commented 3 years ago

This issue occurs in UICollectionView usually when implementing self-sizing cells but there are workarounds to get past it. Unfortunately the UICollectionViewDelegateFlowLayout methods we conform to in order to perform the workaround are not accessible when using MagazineLayout. Is there any possibility we can get a fix for this within MagazineLayout?

Danie1s commented 2 years ago

use .static heightMode can solve this problem

alexookah commented 1 year ago

I am also experiencing this problem. Are there any plans to fix it? Similar issue was happening on rotation and was fixed. Maybe the same resolution could also be applied here. @maxcox Could you share your UICollectionViewDelegateFlowLayout methods that get past this problem?

elliot-vu commented 1 year ago

Good news! My PR is merged into the master branch. #113 I have a approach that cache collection view cell height when cell will appear. And input to sizeModeForItemAt delegate method. It look like this:

func collectionView(
    _ collectionView: UICollectionView,
    layout collectionViewLayout: UICollectionViewLayout,
    sizeModeForItemAt indexPath: IndexPath)
    -> MagazineLayoutItemSizeMode {
  if let cachedHeight = cachedHeightStorage[indexPath] {
     return MagazineLayoutItemSizeMode(widthMode: fullWidth(respectsHorizontalInsets: 10), heightMode: .dynamic(estimatedHeight : cachedHeight))
  }

  return MagazineLayoutItemSizeMode(widthMode: fullWidth(respectsHorizontalInsets: 10), heightMode: .dynamic)
}