Xamarin.Forms
Xamarin.Forms copied to clipboard
CollectionView fails on iOS for version 5.0.0.2401
Description
CollectionView no longer works on iOS 15.4 for version 5.0.0.2401. The items are not displayed and the Application Output has a lot of repeated error messages:
**The behavior of the UICollectionViewFlowLayout is not defined because: the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
Please check the values returned by the delegate. The relevant UICollectionViewFlowLayout instance is <Xamarin_Forms_Platform_iOS_ListViewLayout: 0x7faf82745b80>, and it is attached to <UICollectionView: 0x7faf83715c00; frame = (0 0; 350 789); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x600003cac720>; layer = <CALayer: 0x6000035b96e0>; contentOffset: {0, 0}; contentSize: {0, 0}; adjustedContentInset: {0, 0, 0, 0}; layout: <Xamarin_Forms_Platform_iOS_ListViewLayout: 0x7faf82745b80>; dataSource: <Xamarin_Forms_Platform_iOS_GroupableItemsViewController_1: 0x7faf82745dc0>>. 2022-04-19 09:01:35.558971+0200 CollectionViewTutorial.iOS[20419:17713466] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.**
Steps to Reproduce
- Download CollectionViewTutorial from https://github.com/xamarin/xamarin-forms-samples/tree/main/GetStarted/Tutorials/CollectionViewTutorial
- Run it on iOS 15.4 in simulator
- Observe that it works
- Upgrade XF to 5.0.0.2401
- Run it again on iOS 15.4 in simulator
- Observe the missing output and the errors in the output
Expected Behavior
I would expected items to be displayed and no UICollectionView errors in the log
Actual Behavior
No items are displayed and there are errors in the log
Basic Information
- Version with issue: 5.0.0.2401
- Last known good version: 5.0.0.2337
- iOS: 15.4
Workaround
Downgrade to XF 5.0.0.2337
It seems related to https://github.com/xamarin/Xamarin.Forms/issues/13323
There is only one solution to fix this CollectionView hell on iOS. Fix it definetely. 5 years that it's flowed. I proposed to fix it definetely as i already did it in mvvmcross. But get no echo.
Not sure what you mean @softlion but if you have some ideas on how to fix CollectionView issues, I'm very open to your PRs!
Not sure what you mean @softlion but if you have some ideas on how to fix CollectionView issues, I'm very open to your PRs!
Would that go into maui, or is it the same code for maui ?
Hello, We encounter the same problem (iOS only) and it prevent us to upgrade from XF 4.8 to 5.0.0.x. We are also using Mvvmcross. From what i see, in my case, this problem occurs when collectionViews are embedded in a stacklayout on which we play with the IsVisible property.
I believe we are at a junction where we (and the major client I'm working for) will have to stop using CollectionView due to it's iOS problems. The workarounds like MeasureFirstItem does not seem to work in all cases. I dare not go back to the ListView, so I'm contemplating using https://github.com/roubachof/Sharpnado.CollectionView or perhaps the control from SyncFusion.
Observe the same issue for CarouselView, which uses CollectionView under the hoods. Reverting from 5.0.0.2401 to 5.0.0.2337 resolved the issue.
@jfversluis The problem is your use of FlowLayout to do something it wasn’t designed for.
Don’t size collection view cells based on math while using FlowLayout - it’s too picky and you’ll never get the math right. Or it will just crash on you. You’re constantly competing against whatever layout code Apple wrote.
Instead, write a new Layout that does the math/calls Measure/whatever instead. There are some nice WWDC videos on how to write custom layouts for CollectionView. That way you are guaranteed to get the cell sizes you want, you can put them where you want, and you won’t be fighting Apple’s default layout.
Isse still present in latest Xamarin.Forms 5.0.0.2515, but not in older 5.0.0.2337.
See the two possible work-arounds in #13323:
-
ItemSizingStrategy="MeasureFirstItem"
. - Display at first with no items. After a slight delay, add the items.
Don't worry guys, just tell your users to wait, recode to use MAUI, wait another year for MS to fix it on MAUI and then when all that doesn't yet work just hand code something yourself. Great example here of why XF (maybe MAUI) won't catch on. Not enough testing by MS, minimal support and issues that last for many years while MS are busy creating the next MAUI is wonderful video.
Let's hope that MS will attend to it soon. But it has surfaced something about the abstraction principle I previously didn't consider when comparing to drawn controls; That the developers aren't necessarily skilled enough to do a proper encapsulation of the underlying system control. They don't necessarily know the do's and the don'ts of the platform.
Will PR something, definetly, as the current maui version is unusable. I can't release my app update because of it.
note that in XF, the easy fix is to await Task.Delay(1) after EVERY collection viewmodel update.
Timing hacks are not easily applicable to reactive architectures, like DynamicData's SourceCache that maintains the items in the collection. Neither should they be.
Any update from anyone ?
This bug is affecting CarouselView for us.
Downgrading to 2337 from 2515 isn't an option due to other dependencies. Task.Delay(50) after setting the view model doesn't work either. There is no ItemSizingStrategy for CarouselView so even if I wanted to (which I don't) I can't set this.
A pretty serious regression no?
Any update from anyone ?
If its useful to anyone on this thread (while waiting for an official fix) Ive found this (not so pretty) workaround for my specific case:
I have a CollectionView in a sfPopUp (Syncfusion Popup)). On showing the Popup the collection view is empty (using "color blended layers" in the simulator revealed that there were indeed items in my collection view, they were just not visible). Changing orientation of the device re-rendered the screen and the CollectionView was now visible.
The Workaround:
I created a bindable property to the viewmodel, bool isCollectionViewVisible (default false); Then on the page I bind the IsVisible property of the collection view to the isCollectionViewVisible property.
Setting the isCollectionViewVisible property to true now re-renders the CollectionView and everything is fine. This can then be done after the popup is opened (or the OnAppearing event, given that the underlying viewmodel is populated and ready to go).
Not proud of the workaround but it works.
It seems there is some kind of issue with the timing of the various events when rendering on iOS.
I'm having the same issue with version 5.0.0.2515, so far I downgraded to 5.0.0.2478 and it works.
Any update regarding this issue? It looks strange that no updates, because it's something that breaks CollectionView in my case and no items are visible.
I have a fix until Microsoft decides to fix this in the source code.. I might even propose a PR but I don't have time now. I hope this helps the community in the mean time.
Write your own iOS collection view renderer which overrides SelectLayout
[assembly: ExportRenderer(typeof(CollectionView), typeof(MyCollectionViewRenderer))]
public class MyCollectionViewRenderer : GroupableItemsViewRenderer<GroupableItemsView, GroupableItemsViewController<GroupableItemsView>>
{
protected override ItemsViewLayout SelectLayout()
{
var itemSizingStrategy = ItemsView.ItemSizingStrategy;
var itemsLayout = ItemsView.ItemsLayout;
if (itemsLayout is GridItemsLayout gridItemsLayout)
{
// TODO: implement MyGridViewLayout similarly to MyListViewLayout
return new MyGridViewLayout(gridItemsLayout, itemSizingStrategy);
}
if (itemsLayout is LinearItemsLayout listItemsLayout)
{
return new MyListViewLayout(listItemsLayout, itemSizingStrategy, ItemsView);
}
// Fall back to vertical list
return new MyListViewLayout(new LinearItemsLayout(ItemsLayoutOrientation.Vertical), itemSizingStrategy, ItemsView);
}
}
Write your own list view layout which overrides ConstrainTo
public class MyListViewLayout : ItemsViewLayout
{
private readonly GroupableItemsView _itemsView;
public MyListViewLayout(LinearItemsLayout itemsLayout, ItemSizingStrategy itemSizingStrategy, GroupableItemsView itemsView)
: base(itemsLayout, itemSizingStrategy)
{
_itemsView = itemsView;
}
public override void ConstrainTo(CGSize size)
{
// See
// - https://stackoverflow.com/questions/55667820/frame-size-of-uicollectionview-is-bigger-than-size-of-uiscreen
// - https://github.com/xamarin/Xamarin.Forms/issues/15320
var constrainedItemsViewDimension =
ScrollDirection == UICollectionViewScrollDirection.Vertical
? _itemsView.Width
: _itemsView.Height;
var constrainedDimension =
ScrollDirection == UICollectionViewScrollDirection.Vertical
? size.Width
: size.Height;
// When ItemsView dimension is available (>0) constrain to it
if (constrainedItemsViewDimension > 0 && constrainedItemsViewDimension < constrainedDimension)
{
constrainedDimension = (float)constrainedItemsViewDimension;
}
ConstrainedDimension = (float)Math.Floor(constrainedDimension);
DetermineCellSize();
}
Is there something similar for maui ?
@albyrock87 thank you for that code snippet, seems to work fine. Could anyone from MS tell me how to create a PR to fix this? I mean, what will be necessary for it to actually get merged