diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
index ab9c3ab2c..0af75d518 100644
--- a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
@@ -151,6 +151,7 @@
+
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/cardBackground.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/cardBackground.png
new file mode 100644
index 000000000..b5b6d1fa4
Binary files /dev/null and b/Xamarin.Forms.ControlGallery.WindowsUniversal/cardBackground.png differ
diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselItemsGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselItemsGallery.cs
index e4419a2aa..a7d205d9f 100644
--- a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselItemsGallery.cs
+++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselItemsGallery.cs
@@ -10,9 +10,17 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
[Preserve(AllMembers = true)]
public class CarouselItemsGallery : ContentPage
{
- public CarouselItemsGallery(bool empty, bool async, bool nativeIndicator)
+ CarouselItemsGalleryViewModel _viewModel;
+ bool _setPositionOnAppering;
+ public CarouselItemsGallery(bool startEmptyCollection = false, bool setCollectionWithAsync = false,
+ bool useNativeIndicators = false, bool setPositionOnConstructor = false,
+ bool setPositionOnAppearing = false, bool useScrollAnimated = true)
{
- var viewModel = new CarouselItemsGalleryViewModel(empty, async);
+ _viewModel = new CarouselItemsGalleryViewModel(startEmptyCollection, setCollectionWithAsync);
+ _setPositionOnAppering = setPositionOnAppearing;
+
+ if (setPositionOnConstructor)
+ _viewModel.CarouselPosition = 3;
Title = $"CarouselView (Indicators)";
@@ -39,14 +47,14 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
{
ItemsLayout = itemsLayout,
ItemTemplate = itemTemplate,
- IsScrollAnimated = true,
+ IsScrollAnimated = useScrollAnimated,
IsBounceEnabled = true,
EmptyView = "This is the empty view",
PeekAreaInsets = new Thickness(50),
- BindingContext = viewModel
};
- carouselView.SetBinding(CarouselView.ItemsSourceProperty, nameof(viewModel.Items));
+ carouselView.SetBinding(CarouselView.ItemsSourceProperty, nameof(_viewModel.Items));
+ carouselView.SetBinding(CarouselView.PositionProperty, nameof(_viewModel.CarouselPosition));
var absolute = new AbsoluteLayout();
absolute.Children.Add(carouselView, new Rectangle(0, 0, 1, 1), AbsoluteLayoutFlags.All);
@@ -59,7 +67,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
IndicatorsShape = IndicatorShape.Square
};
- if (!nativeIndicator)
+ if (!useNativeIndicators)
{
indicators.IndicatorTemplate = new DataTemplate(() =>
{
@@ -92,12 +100,12 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
addItemButton.Clicked += (sender, e) =>
{
- viewModel.Items.Add(new CarouselData
+ _viewModel.Items.Add(new CarouselData
{
Color = Color.Red,
- Name = $"{viewModel.Items.Count + 1}"
+ Name = $"{_viewModel.Items.Count + 1}"
});
- carouselView.Position = viewModel.Items.Count - 1;
+ _viewModel.CarouselPosition = _viewModel.Items.Count - 1;
};
var removeItemButton = new Button
@@ -107,11 +115,11 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
removeItemButton.Clicked += (sender, e) =>
{
- if (viewModel.Items.Any())
- viewModel.Items.RemoveAt(viewModel.Items.Count - 1);
+ if (_viewModel.Items.Any())
+ _viewModel.Items.RemoveAt(_viewModel.Items.Count - 1);
- if (viewModel.Items.Count > 0)
- carouselView.Position = viewModel.Items.Count - 1;
+ if (_viewModel.Items.Count > 0)
+ _viewModel.CarouselPosition = _viewModel.Items.Count - 1;
};
var clearItemsButton = new Button
@@ -121,7 +129,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
clearItemsButton.Clicked += (sender, e) =>
{
- viewModel.Items.Clear();
+ _viewModel.Items.Clear();
};
var lbl = new Label();
@@ -136,7 +144,15 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
grid.Children.Add(stacklayoutButtons, 0, 1);
Content = grid;
- BindingContext = viewModel;
+ BindingContext = _viewModel;
+ }
+
+ protected override void OnAppearing()
+ {
+ if (_viewModel.CarouselPosition != 3)
+ _viewModel.CarouselPosition = 3;
+
+ base.OnAppearing();
}
internal DataTemplate GetCarouselTemplate()
@@ -193,6 +209,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
public class CarouselItemsGalleryViewModel : BindableObject
{
ObservableCollection _items;
+ int _carouselPosition;
public CarouselItemsGalleryViewModel(bool empty, bool async)
{
@@ -244,5 +261,15 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
OnPropertyChanged(nameof(Items));
}
}
+
+ public int CarouselPosition
+ {
+ get => _carouselPosition;
+ set
+ {
+ _carouselPosition = value;
+ OnPropertyChanged(nameof(CarouselPosition));
+ }
+ }
}
}
diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselViewGallery.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselViewGallery.cs
index 488b9e3b0..8d529191a 100644
--- a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselViewGallery.cs
+++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselViewGallery.cs
@@ -34,11 +34,11 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
GalleryBuilder.NavButton("CarouselView (XAML, Horizontal)", () =>
new CarouselXamlGallery(), Navigation),
GalleryBuilder.NavButton("CarouselView (Indicators Forms)", () =>
- new CarouselItemsGallery(false,false,false), Navigation),
+ new CarouselItemsGallery(), Navigation),
GalleryBuilder.NavButton("CarouselView (Indicators Default (Native))", () =>
- new CarouselItemsGallery(false,false,true), Navigation),
+ new CarouselItemsGallery(useNativeIndicators: true), Navigation),
GalleryBuilder.NavButton("CarouselView Async", () =>
- new CarouselItemsGallery(false,true,true), Navigation),
+ new CarouselItemsGallery(setCollectionWithAsync:true, useNativeIndicators: true), Navigation),
GalleryBuilder.NavButton("CarouselView Snap", () =>
new CarouselSnapGallery(), Navigation),
GalleryBuilder.NavButton("ObservableCollection and CarouselView", () =>
@@ -46,7 +46,13 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
GalleryBuilder.NavButton("CarouselView EmptyView", () =>
new EmptyCarouselGallery(), Navigation),
GalleryBuilder.NavButton("IndicatorView", () =>
- new IndicatorCodeGallery(), Navigation)
+ new IndicatorCodeGallery(), Navigation),
+ GalleryBuilder.NavButton("CarouselView SetPosition Ctor", () =>
+ new CarouselItemsGallery(useNativeIndicators: true, setPositionOnConstructor: true), Navigation),
+ GalleryBuilder.NavButton("CarouselView SetPosition Appearing", () =>
+ new CarouselItemsGallery(useNativeIndicators: true, setPositionOnAppearing: true), Navigation),
+ GalleryBuilder.NavButton("CarouselView SetPosition Ctor No Animation", () =>
+ new CarouselItemsGallery(useNativeIndicators: true, setPositionOnConstructor: true, useScrollAnimated: false), Navigation),
}
}
};
diff --git a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselXamlGallery.xaml.cs b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselXamlGallery.xaml.cs
index 2dadd31ef..ab738fbef 100644
--- a/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselXamlGallery.xaml.cs
+++ b/Xamarin.Forms.Controls/GalleryPages/CollectionViewGalleries/CarouselViewGalleries/CarouselXamlGallery.xaml.cs
@@ -17,7 +17,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
protected override void OnAppearing()
{
base.OnAppearing();
- // (BindingContext as CarouselViewModel).Position = 2;
+ //(BindingContext as CarouselViewModel).Position = 2;
}
}
@@ -45,7 +45,7 @@ namespace Xamarin.Forms.Controls.GalleryPages.CollectionViewGalleries.CarouselVi
switch (_type)
{
case CarouselXamlSampleType.Peek:
- items.Add(new CarouselItem(i, "cardBackground"));
+ items.Add(new CarouselItem(i, "cardBackground.png"));
break;
default:
items.Add(new CarouselItem(i));
diff --git a/Xamarin.Forms.Core.UITests.Shared/Tests/CarouselViewUITests.cs b/Xamarin.Forms.Core.UITests.Shared/Tests/CarouselViewUITests.cs
index d74b660bd..10dfd8653 100644
--- a/Xamarin.Forms.Core.UITests.Shared/Tests/CarouselViewUITests.cs
+++ b/Xamarin.Forms.Core.UITests.Shared/Tests/CarouselViewUITests.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
using NUnit.Framework;
using Xamarin.UITest;
@@ -190,14 +190,22 @@ namespace Xamarin.Forms.Core.UITests
void VisitSubGallery(string galleryName, bool enableIndicator = false)
{
+ App.ScrollUp();
+ App.ScrollUp();
+
if (enableIndicator)
App.Tap(t => t.Marked("EnableIndicatorView"));
App.QueryUntilPresent(() =>
{
- App.ScrollDown();
- return App.Query(t => t.Marked(galleryName));
- });
+ var query = App.Query(t => t.Marked(galleryName));
+ if (query.Count() == 0)
+ {
+ App.ScrollDown();
+ return null;
+ }
+ return query;
+ }, delayInMs: 500);
App.Tap(t => t.Marked(galleryName));
}
diff --git a/Xamarin.Forms.Platform.Android/CollectionView/CarouselViewRenderer.cs b/Xamarin.Forms.Platform.Android/CollectionView/CarouselViewRenderer.cs
index 36440e993..7417101dd 100644
--- a/Xamarin.Forms.Platform.Android/CollectionView/CarouselViewRenderer.cs
+++ b/Xamarin.Forms.Platform.Android/CollectionView/CarouselViewRenderer.cs
@@ -62,7 +62,6 @@ namespace Xamarin.Forms.Platform.Android
AddLayoutListener();
UpdateIsSwipeEnabled();
UpdateIsBounceEnabled();
- UpdateInitialPosition();
UpdateItemSpacing();
}
@@ -131,7 +130,6 @@ namespace Xamarin.Forms.Platform.Android
if (adapter != null)
{
adapter.NotifyItemChanged(_oldPosition);
- Carousel.ScrollTo(_oldPosition, position: Xamarin.Forms.ScrollToPosition.Center);
}
base.UpdateItemSpacing();
@@ -192,11 +190,14 @@ namespace Xamarin.Forms.Platform.Android
ItemsViewAdapter = new ItemsViewAdapter(ItemsView,
(view, context) => new SizedItemContentView(Context, GetItemWidth, GetItemHeight));
-
-
+
_gotoPosition = -1;
+
SwapAdapter(ItemsViewAdapter, false);
+
+ if (_oldPosition > 0)
+ UpdateInitialPosition();
if (ItemsViewAdapter?.ItemsSource is ObservableItemsSource observableItemsSource)
observableItemsSource.CollectionItemsSourceChanged += CollectionItemsSourceChanged;
@@ -297,7 +298,10 @@ namespace Xamarin.Forms.Platform.Android
_oldPosition = position;
+ _gotoPosition = _oldPosition;
+
SetCurrentItem(_oldPosition);
+ Carousel.ScrollTo(_oldPosition, position: Xamarin.Forms.ScrollToPosition.Center, animate: Carousel.AnimatePositionChanges);
}
void UpdateVisualStates()
@@ -406,7 +410,12 @@ namespace Xamarin.Forms.Platform.Android
var carouselPosition = Carousel.Position;
if (itemCount == 0)
+ {
+ //we are trying to set a position but our Collection doesn't have items still
+ _oldPosition = carouselPosition;
return;
+ }
+
if (carouselPosition >= itemCount || carouselPosition < 0)
throw new IndexOutOfRangeException($"Can't set CarouselView to position {carouselPosition}. ItemsSource has {itemCount} items.");
@@ -443,9 +452,9 @@ namespace Xamarin.Forms.Platform.Android
{
if (!_initialized)
{
+ UpdateInitialPosition();
Carousel.Scrolled += CarouselViewScrolled;
- UpdateInitialPosition();
_initialized = true;
}
diff --git a/Xamarin.Forms.Platform.iOS/CollectionView/CarouselViewController.cs b/Xamarin.Forms.Platform.iOS/CollectionView/CarouselViewController.cs
index d4be0581c..678b8839f 100644
--- a/Xamarin.Forms.Platform.iOS/CollectionView/CarouselViewController.cs
+++ b/Xamarin.Forms.Platform.iOS/CollectionView/CarouselViewController.cs
@@ -9,7 +9,7 @@ namespace Xamarin.Forms.Platform.iOS
{
protected readonly CarouselView Carousel;
- bool _viewInitialized;
+ bool _initialPositionSet;
List _oldViews;
int _gotoPosition = -1;
@@ -33,21 +33,10 @@ namespace Xamarin.Forms.Platform.iOS
return cell;
}
- public override void ViewWillLayoutSubviews()
- {
- base.ViewWillLayoutSubviews();
- if (!_viewInitialized)
- {
- _viewInitialized = true;
- UpdateInitialPosition();
- }
-
- UpdateVisualStates();
- }
-
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
+ UpdateInitialPosition();
}
public override void DraggingStarted(UIScrollView scrollView)
@@ -65,6 +54,8 @@ namespace Xamarin.Forms.Platform.iOS
UnsubscribeCollectionItemsSourceChanged(ItemsSource);
base.UpdateItemsSource();
SubscribeCollectionItemsSourceChanged(ItemsSource);
+ _initialPositionSet = false;
+ UpdateInitialPosition();
}
protected override bool IsHorizontal => (Carousel?.ItemsLayout as ItemsLayout)?.Orientation == ItemsLayoutOrientation.Horizontal;
@@ -200,18 +191,18 @@ namespace Xamarin.Forms.Platform.iOS
void UpdateFromCurrentItem()
{
var currentItemPosition = GetIndexForItem(Carousel.CurrentItem).Row;
-
- ScrollToPosition(currentItemPosition, Carousel.Position);
+
+ ScrollToPosition(currentItemPosition, Carousel.Position, Carousel.AnimateCurrentItemChanges);
UpdateVisualStates();
}
- void ScrollToPosition(int goToPosition, int carouselPosition)
+ void ScrollToPosition(int goToPosition, int carouselPosition, bool animate, bool forceScroll = false)
{
- if (_gotoPosition == -1 && goToPosition != carouselPosition)
+ if (_gotoPosition == -1 && (goToPosition != carouselPosition || forceScroll))
{
_gotoPosition = goToPosition;
- Carousel.ScrollTo(goToPosition, position: Xamarin.Forms.ScrollToPosition.Center, animate: Carousel.AnimateCurrentItemChanges);
+ Carousel.ScrollTo(goToPosition, position: Xamarin.Forms.ScrollToPosition.Center, animate: animate);
}
}
@@ -222,35 +213,39 @@ namespace Xamarin.Forms.Platform.iOS
if (carouselPosition == _gotoPosition)
_gotoPosition = -1;
- if(!Carousel.IsDragging)
- ScrollToPosition(carouselPosition, currentItemPosition);
+ if (!Carousel.IsDragging)
+ ScrollToPosition(carouselPosition, currentItemPosition, Carousel.AnimatePositionChanges);
SetCurrentItem(carouselPosition);
}
void UpdateInitialPosition()
{
- if (Carousel.CurrentItem != null)
+ var itemsCount = ItemsSource?.ItemCount;
+
+ if (itemsCount == 0)
+ return;
+
+ if (!_initialPositionSet)
{
- int position = 0;
+ _initialPositionSet = true;
- var items = Carousel.ItemsSource as IList;
-
- for (int n = 0; n < items?.Count; n++)
+ int position = Carousel.Position;
+ var currentItem = Carousel.CurrentItem;
+ if (currentItem != null)
{
- if (items[n] == Carousel.CurrentItem)
- {
- position = n;
- break;
- }
+ position = ItemsSource.GetIndexForItem(currentItem).Row;
+ }
+ else
+ {
+ SetCurrentItem(position);
}
- ScrollToPosition(position, Carousel.Position);
- }
- else
- {
- SetCurrentItem(Carousel.Position);
+ if (position > 0)
+ ScrollToPosition(position, Carousel.Position, Carousel.AnimatePositionChanges, true);
}
+
+ UpdateVisualStates();
}
void UpdateVisualStates()
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/IndicatorViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/IndicatorViewRenderer.cs
index ecd349992..26764a413 100644
--- a/Xamarin.Forms.Platform.iOS/Renderers/IndicatorViewRenderer.cs
+++ b/Xamarin.Forms.Platform.iOS/Renderers/IndicatorViewRenderer.cs
@@ -186,7 +186,9 @@ namespace Xamarin.Forms.Platform.iOS
if (UIPager == null)
return;
- UIPager.Pages = GetMaximumVisible();
+ UIPager.Pages = GetMaximumVisible();
+
+ UpdateCurrentPage();
}
void UpdateHidesForSinglePage()