From 35338be08212c832c9bd60248c91042947ae2f28 Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Tue, 11 Nov 2025 18:21:48 +0530 Subject: [PATCH 1/6] fix the current item and position issue --- .../Handlers/Items2/iOS/LayoutFactory2.cs | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs index 7afb1a9689d6..267d760cd52b 100644 --- a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs @@ -345,16 +345,32 @@ public static UICollectionViewLayout CreateCarouselLayout( return; } - var page = (offset.X + sectionMargin) / (env.Container.ContentSize.Width - sectionMargin * 2); + // Calculate page based on orientation + double page; + if (isHorizontal) + { + page = (offset.X + sectionMargin) / (env.Container.ContentSize.Width - sectionMargin * 2); + } + else + { + page = (offset.Y + sectionMargin) / (env.Container.ContentSize.Height - sectionMargin * 2); + } + + System.Diagnostics.Debug.WriteLine($"Scroll - isHorizontal: {isHorizontal}, offset: {(isHorizontal ? offset.X : offset.Y)}, contentSize: {(isHorizontal ? env.Container.ContentSize.Width : env.Container.ContentSize.Height)}, sectionMargin: {sectionMargin}, page: {page}"); - if (Math.Abs(page % 1) > (double.Epsilon * 100) || cv2Controller.ItemsSource.ItemCount <= 0) + // For horizontal, orthogonal scrolling behavior handles paging, so we only update on exact pages + // For vertical, there's no orthogonal scrolling, so we need to round to nearest page + double pageThreshold = isHorizontal ? (double.Epsilon * 100) : 0.05; // 5% threshold for vertical + + if (Math.Abs(page % 1) > pageThreshold || cv2Controller.ItemsSource.ItemCount <= 0) { + System.Diagnostics.Debug.WriteLine("Returning from CreateCarouselLayout - fractional page or no items"); return; } - var pageIndex = (int)page; + // Round to nearest integer for the page index + var pageIndex = (int)Math.Round(page); var carouselPosition = pageIndex; - if (itemsView.Loop && cv2Controller.ItemsSource is ILoopItemsViewSource loopSource) { var maxIndex = loopSource.LoopCount - 1; @@ -398,7 +414,9 @@ public static UICollectionViewLayout CreateCarouselLayout( } //Update the CarouselView position + System.Diagnostics.Debug.WriteLine($" Before CreateCarouselLayout: {carouselPosition}"); cv2Controller?.SetPosition(carouselPosition); + System.Diagnostics.Debug.WriteLine($"After CreateCarouselLayout: {carouselPosition}"); }; return section; From 3c9703e36444f8dd9e1cf873f2e8a58cff8305b2 Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Wed, 12 Nov 2025 16:50:05 +0530 Subject: [PATCH 2/6] Modified the fix --- .../Core/Handlers/Items2/iOS/LayoutFactory2.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs index 267d760cd52b..181c04652d4e 100644 --- a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs @@ -345,7 +345,6 @@ public static UICollectionViewLayout CreateCarouselLayout( return; } - // Calculate page based on orientation double page; if (isHorizontal) { @@ -355,20 +354,15 @@ public static UICollectionViewLayout CreateCarouselLayout( { page = (offset.Y + sectionMargin) / (env.Container.ContentSize.Height - sectionMargin * 2); } - - System.Diagnostics.Debug.WriteLine($"Scroll - isHorizontal: {isHorizontal}, offset: {(isHorizontal ? offset.X : offset.Y)}, contentSize: {(isHorizontal ? env.Container.ContentSize.Width : env.Container.ContentSize.Height)}, sectionMargin: {sectionMargin}, page: {page}"); - - // For horizontal, orthogonal scrolling behavior handles paging, so we only update on exact pages - // For vertical, there's no orthogonal scrolling, so we need to round to nearest page - double pageThreshold = isHorizontal ? (double.Epsilon * 100) : 0.05; // 5% threshold for vertical - + + // Vertical: Scroll stops wherever touch is released (no auto-centering), so use 0.1 (10%) threshold + // to accept positions near page boundaries where scroll naturally settles + double pageThreshold = isHorizontal ? (double.Epsilon * 100) : 0.1; if (Math.Abs(page % 1) > pageThreshold || cv2Controller.ItemsSource.ItemCount <= 0) { - System.Diagnostics.Debug.WriteLine("Returning from CreateCarouselLayout - fractional page or no items"); return; } - // Round to nearest integer for the page index var pageIndex = (int)Math.Round(page); var carouselPosition = pageIndex; if (itemsView.Loop && cv2Controller.ItemsSource is ILoopItemsViewSource loopSource) @@ -414,9 +408,7 @@ public static UICollectionViewLayout CreateCarouselLayout( } //Update the CarouselView position - System.Diagnostics.Debug.WriteLine($" Before CreateCarouselLayout: {carouselPosition}"); cv2Controller?.SetPosition(carouselPosition); - System.Diagnostics.Debug.WriteLine($"After CreateCarouselLayout: {carouselPosition}"); }; return section; From 0596abab908d181b071344233e812efec4725e21 Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:15:02 +0530 Subject: [PATCH 3/6] Add test case --- .../Handlers/Items2/iOS/LayoutFactory2.cs | 4 +- .../TestCases.HostApp/Issues/Issue32136.cs | 66 +++++++++++++++++++ .../Tests/Issues/Issue32136.cs | 25 +++++++ 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs index 181c04652d4e..f199794420f8 100644 --- a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs @@ -354,7 +354,7 @@ public static UICollectionViewLayout CreateCarouselLayout( { page = (offset.Y + sectionMargin) / (env.Container.ContentSize.Height - sectionMargin * 2); } - + // Vertical: Scroll stops wherever touch is released (no auto-centering), so use 0.1 (10%) threshold // to accept positions near page boundaries where scroll naturally settles double pageThreshold = isHorizontal ? (double.Epsilon * 100) : 0.1; @@ -363,7 +363,7 @@ public static UICollectionViewLayout CreateCarouselLayout( return; } - var pageIndex = (int)Math.Round(page); + var pageIndex = (int)page; var carouselPosition = pageIndex; if (itemsView.Loop && cv2Controller.ItemsSource is ILoopItemsViewSource loopSource) { diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs new file mode 100644 index 000000000000..abfe81fc7e3c --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs @@ -0,0 +1,66 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 32136, "CarouselView CurrentItem Not Updating with Vertical LinearItemsLayout", PlatformAffected.iOS)] +public class Issue32136 : ContentPage +{ + public Issue32136() + { + CarouselView1 carouselView = new CarouselView1 + { + HeightRequest = 400, + Loop = false, + BackgroundColor = Colors.LightGray, + AutomationId = "TestCarouselView", + ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical), + ItemTemplate = new DataTemplate(() => + { + Label label = new Label + { + HorizontalOptions = LayoutOptions.Center, + VerticalOptions = LayoutOptions.Center + }; + label.SetBinding(Label.TextProperty, "."); + + return new Grid + { + Children = { label } + }; + }), + ItemsSource = new string[] + { + "Baboon", + "Capuchin Monkey", + "Blue Monkey", + "Squirrel Monkey", + "Golden Lion Tamarin" + } + }; + + Label currentItemLabel = new Label + { + AutomationId = "CurrentItemLabel" + }; + currentItemLabel.SetBinding(Label.TextProperty, "."); + + carouselView.CurrentItemChanged += (s, e) => + { + currentItemLabel.Text = $"CurrentItem = {e.CurrentItem}"; + }; + + Grid grid = new Grid + { + Padding = 25, + RowSpacing = 10, + RowDefinitions = + { + new RowDefinition(GridLength.Auto), + new RowDefinition(GridLength.Auto), + new RowDefinition(GridLength.Auto) + } + }; + + grid.Add(carouselView); + grid.Add(currentItemLabel, row: 1); + Content = grid; + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs new file mode 100644 index 000000000000..f6fa6ab1d5ce --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs @@ -0,0 +1,25 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue32136 : _IssuesUITest +{ + public Issue32136(TestDevice device) : base(device) + { + } + + public override string Issue => "CarouselView CurrentItem Not Updating with Vertical LinearItemsLayout"; + + [Test] + [Category(UITestCategories.CarouselView)] + public void CurrentItemShouldUpdateWhenScrollingVerticalCarouselView() + { + App.WaitForElement("TestCarouselView"); + App.ScrollDown("TestCarouselView", ScrollStrategy.Gesture, 1.0); + Task.Delay(1500).Wait(); + var currentItemText = App.WaitForElement("CurrentItemLabel").GetText(); + Assert.That(currentItemText, Is.EqualTo("CurrentItem = Capuchin Monkey")); + } +} \ No newline at end of file From fb9529e430ff28ca6ab1d0b9806c2d8cdf11e57e Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Mon, 17 Nov 2025 18:17:23 +0530 Subject: [PATCH 4/6] Modified the test case --- .../Core/Handlers/Items2/iOS/LayoutFactory2.cs | 1 + .../TestCases.HostApp/Issues/Issue32136.cs | 18 +++++++++++------- .../Tests/Issues/Issue32136.cs | 5 ++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs index f199794420f8..679c030d1494 100644 --- a/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs +++ b/src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs @@ -365,6 +365,7 @@ public static UICollectionViewLayout CreateCarouselLayout( var pageIndex = (int)page; var carouselPosition = pageIndex; + if (itemsView.Loop && cv2Controller.ItemsSource is ILoopItemsViewSource loopSource) { var maxIndex = loopSource.LoopCount - 1; diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs index abfe81fc7e3c..52183bb7ce08 100644 --- a/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs @@ -5,7 +5,7 @@ public class Issue32136 : ContentPage { public Issue32136() { - CarouselView1 carouselView = new CarouselView1 + CarouselView2 carouselView = new CarouselView2 { HeightRequest = 400, Loop = false, @@ -36,15 +36,18 @@ public Issue32136() } }; - Label currentItemLabel = new Label + Label currentItemLabel = new Label(); + currentItemLabel.AutomationId = "CurrentItemLabel"; + currentItemLabel.SetBinding(Label.TextProperty, new Binding("CurrentItem", source: carouselView, stringFormat: "CurrentItem = {0}")); + + Button button = new Button { - AutomationId = "CurrentItemLabel" + Text = "Next Item", + AutomationId = "ScrollButton" }; - currentItemLabel.SetBinding(Label.TextProperty, "."); - - carouselView.CurrentItemChanged += (s, e) => + button.Clicked += (s, e) => { - currentItemLabel.Text = $"CurrentItem = {e.CurrentItem}"; + carouselView.ScrollTo(carouselView.Position + 1, position: ScrollToPosition.Center, animate: true); }; Grid grid = new Grid @@ -61,6 +64,7 @@ public Issue32136() grid.Add(carouselView); grid.Add(currentItemLabel, row: 1); + grid.Add(button, row: 2); Content = grid; } } diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs index f6fa6ab1d5ce..c958d69d5688 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32136.cs @@ -16,9 +16,8 @@ public Issue32136(TestDevice device) : base(device) [Category(UITestCategories.CarouselView)] public void CurrentItemShouldUpdateWhenScrollingVerticalCarouselView() { - App.WaitForElement("TestCarouselView"); - App.ScrollDown("TestCarouselView", ScrollStrategy.Gesture, 1.0); - Task.Delay(1500).Wait(); + App.WaitForElement("ScrollButton"); + App.Tap("ScrollButton"); var currentItemText = App.WaitForElement("CurrentItemLabel").GetText(); Assert.That(currentItemText, Is.EqualTo("CurrentItem = Capuchin Monkey")); } From 22604529a312b89b2852596e38f39d6ac3186bdf Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Thu, 20 Nov 2025 12:37:16 +0530 Subject: [PATCH 5/6] Modified the test case --- src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs index 52183bb7ce08..647e720bdd67 100644 --- a/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue32136.cs @@ -38,7 +38,7 @@ public Issue32136() Label currentItemLabel = new Label(); currentItemLabel.AutomationId = "CurrentItemLabel"; - currentItemLabel.SetBinding(Label.TextProperty, new Binding("CurrentItem", source: carouselView, stringFormat: "CurrentItem = {0}")); + currentItemLabel.Text = "CurrentItem = Baboon"; Button button = new Button { @@ -47,9 +47,15 @@ public Issue32136() }; button.Clicked += (s, e) => { + currentItemLabel.Text = "Button was clicked"; carouselView.ScrollTo(carouselView.Position + 1, position: ScrollToPosition.Center, animate: true); }; + carouselView.CurrentItemChanged += (s, e) => + { + currentItemLabel.Text = $"CurrentItem = {e.CurrentItem}"; + }; + Grid grid = new Grid { Padding = 25, From c8b61a916ae588233b3b4e4b11129e70fa0a7241 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 20 Nov 2025 04:48:40 -0600 Subject: [PATCH 6/6] - push up test code --- .../Controls.Sample.Sandbox/MainPage.xaml | 69 ++++++++++++ .../Controls.Sample.Sandbox/MainPage.xaml.cs | 104 +++++++++++++++++- .../Controls.Sample.Sandbox/MauiProgram.cs | 22 +++- 3 files changed, 193 insertions(+), 2 deletions(-) diff --git a/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml b/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml index 7363d18deadd..c3025222f6a5 100644 --- a/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml +++ b/src/Controls/samples/Controls.Sample.Sandbox/MainPage.xaml @@ -2,4 +2,73 @@ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Maui.Controls.Sample.MainPage" xmlns:local="clr-namespace:Maui.Controls.Sample"> + + + + + + + + + + + +