Xamarin.forms: [Bug] CarouselView doesn't update the CurrentItem on Swipe under strange conditions

Created on 3 Mar 2020  路  5Comments  路  Source: xamarin/Xamarin.Forms

Description

When a CarouselView with PeekAreaInsets is inside of a Grid with a * Row, the CurrentItem can lag behind and not represent the visible item that you swipe to.

Appears to require both of those conditions to fail.

Steps to Reproduce

  1. Run repro
  2. Swipe

Expected Behavior

SearchBar and IndicatorView should update to reflect that you've moved to the second item

Actual Behavior

Both SearchBar and IndicatorView are pointing at the first item

Basic Information

  • Version with issue: 4.6.0-pre1
  • Last known good version:
  • IDE:Vs 16.4
  • Platform Target Frameworks:

    • iOS:

    • Android: API 28

    • UWP:

  • Android Support Library Version:
  • Nuget Packages:
  • Affected Devices:

Reproduction Link

PeakyBlunders.zip

Workaround

Don't use PeekAreaInsets or don't use a Grid with * row

carouselview 5 bug

All 5 comments

Thank you! I have been trying to create a reproduction of this, and had been unable.

Interestingly, if I remove all star rows (and columns) in my project by setting them to "Auto", I'm still seeing the bug. And in another project if I deliberately put star rows in... the bug doesn't occur.

It definitely only happens with PeekAreaInsets > 0.

This bug is a real shame, because PeekAreaInsets looks great.

New information; In my project this issue occurs whenever:

  • HeightRequest is set on the CarouselView; and
  • PeekAreaInsets > 0

If I clear HeightRequest attribute from the XAML tag (and the CarouselView isn't in a star row, which also makes sense) then I don't have a problem with PeekAreaInsets > 0.

I haven't had time to see if these two conditions are enough to reproduce the problem in a new, empty project. Will post again if I get around to that.

Workaround:
Enclose the CarouselView in a StackLayout or ContentView. Setting HeightRequest on that parent ContentView/StackLayout allows you to control the height of the CarouselView while simultaneously using PeekAreaInsets > 0 without this IndicatorView issue.

<ContentView HeightRequest="300">
    <CarouselView IndicatorView="[indicator-view-name]">
        ...
    </CarouselView>
</ContentView>

I'm using the follwing grid:

 <Grid HorizontalOptions="Center"
      Padding="10,10,10,40"
      ColumnSpacing="15">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="80" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="80" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="120" />
    </Grid.RowDefinitions>
    <CarouselView Grid.Column="0" Grid.Row="0"
                           PeekAreaInsets="40"
                           IsScrollAnimated="False"
                           IsBounceEnabled="False">
         ...
    </CarouselView>
     ...
    <CarouselView Grid.Column="2" Grid.Row="0"
                           PeekAreaInsets="40"
                           IsScrollAnimated="False"
                           IsBounceEnabled="False">
         ...
    </CarouselView>
    ...
</Grid>

The first CarouselView could detect the scrolling without any problems, but the other had problems as described above where it would lag behind, sometimes not detecting scroll at all.

Doing what @tomeverin said, enclosing the CarouselViews in a StackLayout seems to have fixed the issuee (both my CarouselViews had to be enclosed though)

In @ludas96 example, having the CarouselView in a row with Height="120" is equivalent to having HeightRequest="120" set on the CarouselView.

By putting the HeightRequest on an enclosing StackLayout it allows the CarouselView to fill its parent, and the desired height is instead imposed by the enclosing StackLayout. I think this is why it works.

Why HeightRequest on CarouselView causes the behaviour in the first place, not sure.

Was this page helpful?
0 / 5 - 0 ratings