dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.04k stars 1.73k forks source link

iOS - CollectionView with varying row heights only gives one row of height per item until something triggers a refresh #23123

Open mattkeene opened 3 months ago

mattkeene commented 3 months ago

Description

I have a grouped CollectionView with simple labels as items. Some of these items can be multiple lines long via WordWrap. When I add items to a group, everything works perfectly on Android, but on iOS, the CollectionView only gives one row per item regardless of size, leading to overlapping or partially hidden items. The view only corrects itself when another group is added/removed OR when something triggers a UI refresh such as rotating the screen or scrolling the affected area out of and back into view. I have not found any way to manually trigger a UI recalculation after adding/removing items that properly recalculates. The Collection/Property Changed notifications make the items appear/disappear, but do not properly calculate the size of each item in the CollectionView.

Video screen capture of the issue:

https://github.com/dotnet/maui/assets/3519695/1395b846-9f08-4c17-88be-75d3c49b0f55

Steps to Reproduce

  1. Launch the app on an iOS Simulator or Device
  2. Click Category 1 (note the overlapping items due to only having one row per item including two-line items)
  3. Click Category 2 (Category 1 refreshes and corrects itself - how can I force this back in step 2?)
  4. Click Category 3 (note the final two-line item is cut off as one one row of height was allocated)
  5. Click Category 2 again (Category 3 corrects itself)

Link to public reproduction project repository

https://github.com/mattkeene/CollectionViewRowHeightBugIOS

Version with bug

8.0.60 SR6

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

iOS

Affected platform versions

iOS 17

Did you find any workaround?

The only workaround I have found is to completely clear and reassign the CollectionView.ItemsSource before adding/removing items then reassigning it afterwards, which in effect kills the UI animations and makes the UI jumpy. Also, because it's a brand new list, it jumps to the top of the CollectionView, losing their place.

Relevant log output

No response

github-actions[bot] commented 3 months ago

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

drasticactions commented 3 months ago

Could be similar to https://github.com/dotnet/maui/issues/13451

RoiChen001 commented 3 months ago

Can repro this issue at iOS platform on the latest 17.11.0 Preview 2.0(8.0.60).

Gekidoku commented 3 months ago

This has been in maui for a while now. My workaround is using a scrollview and stacklayout as bindablelayout in ios. gives the behavior i want. but its far from ideal. And even then i sometimes have to trigger redraws on ios. but then i build my views in c# and not in xaml.

#if ANDROID
            RosterScroll = new CollectionView()
            {
                FlowDirection = FlowDirection.LeftToRight,
                ItemTemplate = new RitItemSelector(),
                Margin = 0,

                ItemSizingStrategy = ItemSizingStrategy.MeasureAllItems,

            };

            RosterScroll.SetBinding(CollectionView.ItemsSourceProperty, "TotalList", BindingMode.TwoWay);

            refreshView.Content = RosterScroll;
#elif IOS

            var myscroll = new ScrollView()
            {
                Orientation = ScrollOrientation.Vertical,
                VerticalOptions = LayoutOptions.FillAndExpand,

            };
            var myflex = new StackLayout();

            myflex.SetBinding(BindableLayout.ItemsSourceProperty, "TotalList");
            BindableLayout.SetItemTemplateSelector(myflex, new RitItemSelector());
            myscroll.Content = myflex;
            refreshView.Content = myscroll;

#endif
albyrock87 commented 3 months ago

This is probably a duplicate as mentioned above. Let me just link my PR #23052 which contains the fix.