Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Commit

Permalink
[Android] CarouselView position resets when visibility toggled (#12864)
Browse files Browse the repository at this point in the history
fixes #12848

* Fix issue with CarouselView position and visibility on Android

* Updated instructions

* Added UITest

* Fix the issue
  • Loading branch information
jsuarezruiz committed Jan 20, 2021
1 parent 7c84b2f commit 6f9b1f6
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>

<controls:TestContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Xamarin.Forms.Controls"
x:Class="Xamarin.Forms.Controls.Issues.Issue12848"
Title="Issue 12848">
<StackLayout>
<Label
Padding="12"
BackgroundColor="Black"
TextColor="White"
Text="Swipe the CarouselView to select the item numbered 2. Then, tap the Hide Button to hide the Carousel and the Show Button to show the Carousel again. If the position of the Carousel is the same as before hiding, the test has passed."/>
<CarouselView
AutomationId="TestCarouselView"
x:Name="carousel"
HorizontalOptions="Center"
ItemsSource="{Binding}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Label
Text="{Binding}"
FontSize="96"
HorizontalTextAlignment="Center"/>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Label
AutomationId="CarouselPosition"
Text="{Binding Source={x:Reference carousel}, Path=Position}"
HorizontalOptions="Center"/>
<Button
AutomationId="HideButton"
Text="Hide CarouselView"
Clicked="OnHideButtonClicked"/>
<Button
AutomationId="ShowButton"
Text="Show CarouselView"
Clicked="OnShowButtonClicked"/>
</StackLayout>
</controls:TestContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

#if UITEST
using Xamarin.Forms.Core.UITests;
using NUnit.Framework;
#endif

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 12848, "[Bug] CarouselView position resets when visibility toggled",
PlatformAffected.Android)]
public partial class Issue12848 : TestContentPage
{
protected override void Init()
{
#if APP
InitializeComponent();

BindingContext = new List<int> { 1, 2, 3 };
#endif
}

#if APP
void OnShowButtonClicked(object sender, EventArgs e)
{
carousel.IsVisible = true;
}

void OnHideButtonClicked(object sender, EventArgs e)
{
carousel.IsVisible = false;
}
#endif

#if UITEST
[Test]
public void Issue12848Test()
{
RunningApp.WaitForElement("TestCarouselView");
RunningApp.SwipeRightToLeft();
Assert.AreEqual(1, int.Parse(RunningApp.Query(q => q.Marked("CarouselPosition"))[0].Text));
RunningApp.Tap("HideButton");
RunningApp.Tap("ShowButton");
Assert.AreEqual(1, int.Parse(RunningApp.Query(q => q.Marked("CarouselPosition"))[0].Text));
RunningApp.Screenshot("Test passed");
}
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1682,6 +1682,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue12777.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11911.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue11691.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12848.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12315.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12912.xaml.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue12910.xaml.cs" />
Expand Down Expand Up @@ -2059,6 +2060,9 @@
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue11691.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12848.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue12315.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,21 +334,21 @@ void UpdateItemDecoration()

void UpdateInitialPosition()
{
int position = 0;
int itemCount = 0;
int position;

if (Carousel.CurrentItem != null)
{
var carouselEnumerator = Carousel.ItemsSource.GetEnumerator();
var items = new List<object>();

while (carouselEnumerator.MoveNext())
{
if (carouselEnumerator.Current == Carousel.CurrentItem)
position = itemCount;

items.Add(carouselEnumerator.Current);
itemCount++;
}

position = items.IndexOf(Carousel.CurrentItem);
Carousel.Position = position;
}
else
Expand Down

1 comment on commit 6f9b1f6

@RobertBickers
Copy link

@RobertBickers RobertBickers commented on 6f9b1f6 Mar 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit seems to be causing an issue for me when modifying the source of the collection after the control has been initialised. i.e. If I have the ItemsSource as a bindable property, and then switch it out within my ViewModel.

It could be that this is because I'm using that in combination with the SelectedIndex property, where for some reason this means that the CurrentItem has not yet been set, therefore resulting in the IndexOf returning a -1 as it could not be found.

Because of that, the IndexOutOfRangeException is thrown on line 538 causing android apps to crash:

if (carouselPosition >= itemCount || carouselPosition < 0)
				throw new IndexOutOfRangeException($"Can't set CarouselView to position {carouselPosition}. ItemsSource has {itemCount} items.");

Please sign in to comment.