Xamarin.forms: [Bug] CollectionView iOS items overlap for Grouped data when ItemSizingStrategy not MeasureFirstItem

Created on 22 Dec 2019  路  13Comments  路  Source: xamarin/Xamarin.Forms

Description

On iOS when CollectionView is displaying grouped data ItemSizingStrategy is either not set or is MeasureAllItems, the items displayed in the CollectionView overlap. Does not affect Android.

Steps to Reproduce

  1. Create a new Xamarin iOS app project using usual VS template for to-do list

  2. Create ItemList class for grouped data:

    public class ItemList : ObservableCollection<Item>
    {
        public string GroupDisplayHeading { get; set; } = "";
        public ObservableCollection<Item> ItemLists => this;

    }
  1. Populate a data structure in the ViewModel:
 public class ItemsViewModel : BaseViewModel
    {
        public ObservableCollection<ItemList> GroupedList { get; set; }

        public ItemsViewModel()
        {
            GroupedList = new ObservableCollection<ItemList>();


            ItemList curList = new ItemList();
            curList.GroupDisplayHeading = "Heading 1";
            curList.Add(new Item() { Text = "Item 1" });
            curList.Add(new Item() { Text = "Item 2" });
            curList.Add(new Item() { Text = "Item 3" });
            curList.Add(new Item() { Text = "Item 4" });
            curList.Add(new Item() { Text = "Item 5" });
            curList.Add(new Item() { Text = "Item 6" });

            GroupedList.Add(curList);

            curList = new ItemList();
            curList.GroupDisplayHeading = "Heading 2";
            curList.Add(new Item() { Text = "Item 7" });
            curList.Add(new Item() { Text = "Item 8" });
            curList.Add(new Item() { Text = "Item 9" });
            curList.Add(new Item() { Text = "Item 10" });
            curList.Add(new Item() { Text = "Item 11" });
            curList.Add(new Item() { Text = "Item 12" });

            GroupedList.Add(curList);

        }

    }
  1. Adjust the XAML for ItemsPage.xaml:
 <StackLayout>
        <CollectionView IsGrouped="true" ItemsSource="{Binding GroupedList}" BackgroundColor="White">

            <CollectionView.ItemsLayout>
                <GridItemsLayout Orientation="Vertical" Span="2" />
            </CollectionView.ItemsLayout>

            <CollectionView.GroupHeaderTemplate>
                <DataTemplate>
                    <Grid>
                        <Label Text="{Binding GroupDisplayHeading}" FontSize="Large" Padding="5"/>
                    </Grid>
                </DataTemplate>
            </CollectionView.GroupHeaderTemplate>

            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="120"></RowDefinition>
                        </Grid.RowDefinitions>

                        <Frame Grid.Row="0" HasShadow="True" Margin="10,6,10,6" Padding="3">

                            <StackLayout>
                                <Label Text="{Binding Text}" FontSize="Medium" Margin="0"></Label>
                            </StackLayout>


                        </Frame>
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>
  1. Run in iOS simulator, observe overlap

  2. Add ItemSizingStrategy="MeasureFirstItem" to the CollectionView xaml

  3. Run in iOS simulator, observe no overlap.

Expected Behavior

CollectionView to display grouped data with headings, followed by 2 columns of items without any overlap

Actual Behavior

CollectionView displays grouped data with headings, with 2 columns over overlapping items

Basic Information

  • Version with issue: Xamarin.Forms 4.4.0.991265
  • IDE: Visual Studio 16.4.1

Screenshots

image

image

Reproduction Link

collectionview 3 high impact iOS 馃崕 bug

Most helpful comment

Any updates on this one guys? The CollectionView is totally unusable when using any kind of grouping on it, wrong measurements, item overlapping, native exceptions being thrown :(

All 13 comments

Any ETA or workarounds for this issue?

here is an ugly workaround, not sure if it's exactly this issue but it's at least somehow works without overlapping

        /// <summary>
        /// Ugly fix for https://github.com/xamarin/Xamarin.Forms/issues/9000 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void ItemsList_OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {

            if (Device.RuntimePlatform != Device.iOS)
                return;
            if (!(sender is CollectionView itemsList))
                return;

            await Task.Delay(600);
            itemsList.ScrollTo(itemsSource.LastOrDefault(), null, ScrollToPosition.End, animate: false);
            itemsList.ScrollTo(itemsSource.FirstOrDefault(), null, ScrollToPosition.Start, animate: false);
        }

Any updates on this one guys? The CollectionView is totally unusable when using any kind of grouping on it, wrong measurements, item overlapping, native exceptions being thrown :(

This bug (which still exists in the latest Xamarin Forms 4.6) is currently blocking my company from being able to release our app. Does anyone have any ideas of a workaround? I understand there are other pressing matters but this makes the groupable functionality unusable as winter mentioned above on iOS.

@samhouts This bug is also blocking our app release.

@stepkillah 's workaround improves the situation (fewer overlaps) but the layout is still buggy. For our project, using stepkillah's workaround: the first item in the collection is single column, then the remaining items are all appropriately laid out in 2 columns, but the layout changes while scrolling.

OK, heres my temporary workaround/hack for this bug:

```

1) Item type of the collection

public class GroupableCollectionItem
{
    public bool HeaderIsVisible { get; set; }
    public string Header { get; set; }
     public string Name {get;set;}
}

2) My View Model

public class ViewModel {
public ObservableCollection Items {get;set;}

public void SetItems(List firstGroup, List secondGroup)
{
Items.AddRange( firstGroup.Select((x, index)=>
var isFirstItem = index == 0;
new GroupableCollectionItem{
HeaderIsVisible = isFirstItem,
Header = headerLabel,
Name = x.Name
});
Items.AddRange( secondGroup.Select((x, index)=>
var isFirstItem = index == 0;
new GroupableCollectionItem{
HeaderIsVisible = isFirstItem,
Header = headerLabel,
Name = x.Name
});
}
}

3) My View

ItemSource={Binding Items}
IsGroupable={false}>



Text="{Binding Header}"
IsVisible="{Binding HeaderIsVisible}"/>
Text={Binding Name} />




```

Basically each item template has a "header" label that is only shown if the current item is the first in the particular collection.

Given up on CollectionView for now. I've replaced CollectionView with a series of FlexLayouts using BindableLayout; can achieve the same sort of functionality and works well on both Android and iOS. I'm using one FlexLayout per group, and adding group headers at run time based on the collection.

@samhouts @hartez Hi there, I have converted the app to use collectionview for all the obvious reasons eg performance, we are going live very soon and I have to revert back to Listview as the collection view in IOS does not work as expected especially with grouping or on small devices as mentioned in this bug. In my eyes this is critical as it stops us using the collectionview for many scenarions like grouping. Will this be fixed soon or we are better off using listview for grouping? Many thanks

Here is a reproduction project of the issue https://github.com/kramer-e/CollectionViewGroupingSpan2Issue The issue occurs with iPhones that have smaller screen sizes, such as the iPhone 8 and SE(2nd edition) with iOS 13.5.

CollectionViewSpanIssueIPhoneSE

I'm seeing a similar problem using viewcells in a listview. So just beware that moving to a ListView may not solve problem either.
Tried Xamarin.Forms.4.7.0.968 and a downgrade to 4.6.0.967

I am using ListView without grouping. I have lines in the row that get hidden with the IsVisible property, and those cause overlapping when they are IsVisible="false" when scrolling up/down. Reverting from 4.6.0.967 to 4.6.0.847 resolves.

Check the comment in here. It would solve the issue https://github.com/xamarin/Xamarin.Forms/issues/10842 (atleast it solved for me) :)

Had a similar issue with a grouped collection view header. If I tried to hide/show an item then I would get a weird behaviour having to do probably with the header's height not being updated after it was initially rendered. I managed to address it with a data template selector.

Was this page helpful?
0 / 5 - 0 ratings