xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug] [Android] Collection View wrong first/last item sizing (on Orientation=Vertical and Span > 1) #9125

Closed inimirpaz closed 3 years ago

inimirpaz commented 4 years ago

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

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

keozx commented 4 years ago

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

keozx commented 4 years ago

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

ttmher commented 4 years ago

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

inimirpaz commented 4 years ago

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)

aranor01 commented 4 years ago

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.

IliyanPopov commented 4 years ago

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

ChummerUA commented 4 years ago

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.

ChummerUA commented 4 years ago

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.

chaoyebugao commented 4 years ago

met the same problem.

chaoyebugao commented 4 years ago

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>
ahmedroshdy commented 3 years ago

same issue happens with