Xamarin.forms: [Bug] [Android] Collection View wrong first/last item sizing (on Orientation=Vertical and Span > 1)

Created on 8 Jan 2020  路  10Comments  路  Source: xamarin/Xamarin.Forms

Description

When using a Collection View on Android (any device) with Orientation=Vertical and Span > 1 (to get more than one column), when the DataTemplate is composed of a grid of fixed height and width, if the last item happens to sit on the rightmost slot its height is messed up. Also, the width of the first item is always messed up on ItemSizingStrategy=MeasureFirstItem . (see attached project)

Steps to Reproduce

  1. Have a DataTemplate of a Collection View composed of a Grid view with fixed height (rowdefinitions) and width (columndefinitions)
  2. Populate the ItemSource so that the last item lands on the rightmost column of the collection view.

Expected Behavior

First/last item on a Collection View to always be the size specified by the Grid col/row definitions.

Actual Behavior

If, and only if, the last item happens to sit on the rightmost column in a Collection view it gets its height messed up. If it happens to be in any other column the item gets properly sized.
When the sizing strategy is set to MeasureFirstItem, the first item always gets its width messed up.

Basic Information

  • Version with issue: 4.4.0.991265 (known since at least 4.2, and still present in 4.6.0.129-nightly)
  • Last known good version: N/A
  • IDE: VS for Mac 8.3.11 (build 1)
  • Android: devices with API 23 -> 28 for sure.

Screenshots

Last item (wrong height):
Screen1

When ItemSizingStrategy="MeasureFirstItem", the first item gets wrong width as well:
Screen2

Workaround

Add an "invisible" (enabled=false, visible=false) grid element to the Collection view in order to get the last (visible) item sized properly not being the last item in the collection anymore.

Reproduction Link

CollectionViewBug.zip

collectionview 4 in-progress high impact mobcat Android bug

Most helpful comment

I have the same problem. Adding a footer with an element of 0 height fixed the problem for me.

All 10 comments

A span of 3 or more makes the first row/column's items also bigger than the rest, probably different bug, will try to issue one

There seems to be a nasty issue with HorizontalItemSpacing and VerticalItemSpacing, in my case I could fix my layout wrapping a Grid around the actual item in the template, which should not be needed, but if I set any item spacing it's all messy sizing, this is with a Span of 9 and 45 items, so you are only left with Padding on the Grid as a workaround

I have the same problem. Adding a footer with an element of 0 height fixed the problem for me.

I have the same problem. Adding a footer with an element of 0 height fixed the problem for me.

Nice! Same here, it's a better workaround than mine for sure.
(Not that I was expecting otherwise but ItemSizingStrategy="MeasureFirstItem" still makes the first item wider)

The workaround of adding an "invisible" footer can't be used if you actually need a footer, in fact in this case the footer width will be altered.

Issue sill not resolved. Tested with Xamarin.Forms v4.6.0.529-pre3 (latest pre-release at the moment)

Source of this issue is SpacingItemDecoration
https://github.com/xamarin/Xamarin.Forms/blob/7a52542d50797ccc69ae1d8dd84259190d96bdb4/Xamarin.Forms.Platform.Android/CollectionView/SpacingItemDecoration.cs
The workaround is to create custom ItemDecoration with correct outRect in GetItemsOffset and override CreateSpacingDecoration in CollectionView renderer.

Found out that it's not enough to just fix ItemDecoration's outRect. Decorations are not updated correctly when collection is updated. To fix this you need to notify adapter that collection is updated.

met the same problem.

I solved this by add external StackLayout as parent in DataTemplate then set it's child's background.
Just like below:

<DataTemplate>
    <StackLayout> 
        <Frame CornerRadius="8" IsClippedToBounds="True" Padding="0" >
            <Grid RowSpacing="4" Padding="12,10,10,10" BackgroundColor="LightGray">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <RelativeLayout Grid.Row="0">
                    <Label Text="0"/>
                </RelativeLayout>

                <RelativeLayout Grid.Row="1">
                    <Label Text="1"/>
                </RelativeLayout>

                <RelativeLayout Grid.Row="2">
                    <Label Text="2"/>
                </RelativeLayout>

            </Grid>
        </Frame>
    </StackLayout>
</DataTemplate>
Was this page helpful?
0 / 5 - 0 ratings