-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[Bug] Regression: XF nightly completely broke CollectionView scrolling #13719
Comments
@Tommigun1980 To validate the issue, can use the repro project at #13231 (without changes) just using XF 5.0.1.2000-nightly? |
Hi. Yes. |
Can reproduce the issue. |
Well, this is interesting (and vexing). I can reproduce this problem (or at least the "can't scroll all the way to the bottom" part of it) on notch devices. On an iPhone 8 and SE, everything is peachy. |
... and I take that back. If I deliberately slow down the scrolling with some debugging statements, I can make this fail on an iPhone 8 as well. This appears to be a cache invalidation issue. |
@hartez I have to admit after studying the XF source I'm puzzled as to why it uses its own cell cache when there's already a perfectly good one in iOS. The XF cell cache has been a fertile source of bugs, and I'm not entirely convinced it's necessary. Do things really slow down if the cell cache is removed? |
…hanges by very small amounts Fixes #13719
The cell size cache has only been in Forms since [checks notes] ... 5.0.0. It's closed more bugs than it's opened. Unless you're talking about something else.
Yes, but probably not in the way you're thinking. UICollectionViewFlowLayout's cache works fine if the items you need are already in the cache at the proper size. But for certain situations (e.g., animating add/remove actions), the layout doesn't have cached data. So it has to get size information for cells from somewhere. (To be clear, the add animations aren't so much of a problem; it's the remove animations where things get really ugly.) If you have a constant size set, no problem; UICVFL knows what size the item will be. If there's an estimatedItemSize set, then it can use that size until autolayout kicks in and the cell determines its final size. If the estimated size is pretty accurate, the size fluctuation during animation/layout is pretty minimal, and everything looks fine. The problem comes when the actual final sizes are very different than the estimate. You start to get all kinds of weird ugly things happening during animation; you also end up having weird layout issues during scrolling, because the layout doesn't have good information on cell sizes to lay them out smoothly. The way to deal with this is to implement Which sounds peachy - we can just implement that method, and for every indexPath the layout requests we just figure out what size it should be and return that size. Huzzah! But there's a snag: the flow layout will call this method for every single cell. In Forms, because of databinding, we can't know the final size of ... well, pretty much anything until we've bound it. We can't even know for sure what DataTemplate we'll be inflating until we've run the BindingContext for the item through the DataTemplateSelector. So for every single item in the CollectionView, we would have to run the DataTemplateSelector, get the template, create the template's native content, bind all that, and then finally measure it. Which works fine if you've got a CollectionView with a few dozen items. But it's disastrous (for both speed and memory) if you have a CollectionView with 10,000 items in it. The layout will gleefully ask for every one of them, and Forms will inflate and bind 10,000 items. Then it'll do it again later when you actually scroll to them. So, instead, the Forms implementation of And when autolayout kicks in and the actual Forms measure steps happen, we cache those final values in the Forms layer. That way, in the cases where the UICVFL's cache doesn't have them (remove actions, scrolling around, etc.) we can just return the cached sizes from the Forms implementation of The upside is that it fixes a bunch of our problems with weird layout issues because of wildly varying cell sizes. The obvious downside is that now we have the potential for cache invalidation issues. (Caches are like regexes in this way.) Anyway, that was a big infodump on why we cache cell sizes. I would very much prefer not to have to do it, but so far I don't have a good alternate solution. If someone has a better solution that doesn't require a cache and also scales, I will review that PR with gusto :) |
@hartez Thank you so much for the detailed explanation. In my thinking the role currently played by the Forms cell cache could be played instead by the |
@hartez Hi and thank you for looking into this! Unfortunately the latest nightly build did not solve this even though the fix was committed to the main branch three days ago. Is this fix in the latest nightly? The error still happens both in my main project, and in the repro case when updating to latest nightly. |
Description
Steps to Reproduce
Here is a video of the issue: https://drive.google.com/file/d/1CcDqvFsl8XihcqU-YA57eWQIAjF4PxPs/view?usp=sharing
There are two new issues here with scrolling:
Only tested this on iOS.
Expected Behavior
CollectionView scroll should work.
Actual Behavior
CollectionView starts doing random things when scrolled, and can not be scrolled to bottom.
Basic Information
Environment
Show/Hide Visual Studio info
Build Logs
Screenshots
Reproduction Link
Workaround
None, must downgrade Xamarin.Forms.
Please -- when fixing a bug in CollectionView, run the repro project at #13231 (or another project of equal complexity)! It will save all of us a lot of time. Fixing a bug without running a project that uses said component is a 100% certain way to break something else.
The test project must be complex enough to use more advanced features. It is untenable to fix one thing and break something else, if it can at all be avoided.
Thank you!!
The text was updated successfully, but these errors were encountered: