Xamarin.Forms icon indicating copy to clipboard operation
Xamarin.Forms copied to clipboard

CollectionView fails on iOS for version 5.0.0.2401

Open timahrentlov opened this issue 2 years ago • 19 comments

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

  1. Download CollectionViewTutorial from https://github.com/xamarin/xamarin-forms-samples/tree/main/GetStarted/Tutorials/CollectionViewTutorial
  2. Run it on iOS 15.4 in simulator
  3. Observe that it works
  4. Upgrade XF to 5.0.0.2401
  5. Run it again on iOS 15.4 in simulator
  6. 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

timahrentlov avatar Apr 19 '22 07:04 timahrentlov

It seems related to https://github.com/xamarin/Xamarin.Forms/issues/13323

ajramos27 avatar Apr 26 '22 20:04 ajramos27

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.

softlion avatar May 03 '22 06:05 softlion

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!

jfversluis avatar May 03 '22 14:05 jfversluis

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 ?

softlion avatar May 03 '22 14:05 softlion

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.

plafuma avatar May 12 '22 09:05 plafuma

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.

timahrentlov avatar May 16 '22 09:05 timahrentlov

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.

follesoe avatar Jun 07 '22 09:06 follesoe

@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.

praeclarum avatar Jun 08 '22 13:06 praeclarum

Isse still present in latest Xamarin.Forms 5.0.0.2515, but not in older 5.0.0.2337.

follesoe avatar Aug 02 '22 13:08 follesoe

See the two possible work-arounds in #13323:

  • ItemSizingStrategy="MeasureFirstItem".
  • Display at first with no items. After a slight delay, add the items.

ToolmakerSteve avatar Aug 04 '22 20:08 ToolmakerSteve

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.

rs-mobitech avatar Aug 10 '22 14:08 rs-mobitech

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.

timahrentlov avatar Aug 10 '22 14:08 timahrentlov

Will PR something, definetly, as the current maui version is unusable. I can't release my app update because of it.

softlion avatar Aug 10 '22 16:08 softlion

note that in XF, the easy fix is to await Task.Delay(1) after EVERY collection viewmodel update.

softlion avatar Aug 10 '22 16:08 softlion

Timing hacks are not easily applicable to reactive architectures, like DynamicData's SourceCache that maintains the items in the collection. Neither should they be.

timahrentlov avatar Aug 11 '22 08:08 timahrentlov

Any update from anyone ?

rs-mobitech avatar Aug 23 '22 13:08 rs-mobitech

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 ?

RhomGit avatar Aug 28 '22 04:08 RhomGit

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.

jwoeste avatar Aug 29 '22 11:08 jwoeste

I'm having the same issue with version 5.0.0.2515, so far I downgraded to 5.0.0.2478 and it works.

flacidsnake avatar Sep 14 '22 12:09 flacidsnake

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.

DenisLaky avatar Jan 05 '23 10:01 DenisLaky

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();
        }

albyrock87 avatar May 08 '23 12:05 albyrock87

Is there something similar for maui ?

softlion avatar May 09 '23 05:05 softlion

@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

mrjavicho avatar Sep 18 '23 10:09 mrjavicho