From 5beb51c310c7c4f474d6eb895fa2e83e5b7adc47 Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:43:39 +0530 Subject: [PATCH 1/6] Committed the test cases --- .../TestCases.HostApp/Issues/Issue35700.cs | 91 +++++++++++++++++++ .../Tests/Issues/Issue35700.cs | 26 ++++++ 2 files changed, 117 insertions(+) create mode 100644 src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs new file mode 100644 index 000000000000..231a8a2a8b10 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs @@ -0,0 +1,91 @@ +using System.Collections.ObjectModel; +using Microsoft.Maui.Controls.Shapes; + +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 35700, + "Grouped CollectionView items not rendered properly on Android with GridItemsLayout", + PlatformAffected.Android)] +public class Issue35700 : TestContentPage +{ + protected override void Init() + { + var collectionView = new CollectionView2 + { + AutomationId = "TestCollectionView", + IsGrouped = true, + HorizontalOptions = LayoutOptions.Fill, + Margin = new Thickness(5, 30, 5, 5), + ItemsLayout = new GridItemsLayout(ItemsLayoutOrientation.Vertical) + { + Span = 5, + VerticalItemSpacing = 10, + HorizontalItemSpacing = 10, + }, + GroupHeaderTemplate = new DataTemplate(() => + { + var label = new Label + { + HorizontalOptions = LayoutOptions.Fill, + HorizontalTextAlignment = TextAlignment.Start, + Padding = new Thickness(10), + FontSize = 18, + TextColor = Colors.White, + FontAttributes = FontAttributes.Bold, + BackgroundColor = Colors.Gray, + }; + label.SetBinding(Label.TextProperty, "Name"); + return label; + }), + ItemTemplate = new DataTemplate(() => + { + var label = new Label + { + HorizontalOptions = LayoutOptions.Center, + TextColor = Colors.White, + VerticalOptions = LayoutOptions.Center, + HorizontalTextAlignment = TextAlignment.Center, + }; + label.SetBinding(Label.TextProperty, "."); + + return new Border + { + StrokeShape = new RoundRectangle { CornerRadius = 10 }, + Padding = new Thickness(5), + MinimumWidthRequest = 50, + Stroke = Colors.Transparent, + BackgroundColor = Colors.Gray, + StrokeThickness = 1, + HorizontalOptions = LayoutOptions.Center, + Content = label, + }; + }), + }; + + collectionView.ItemsSource = new ObservableCollection + { + new NumberGroup35700("100s", new List + { + "100", "200", "300", "400", "500", + "600", "700", "800", "900", + }), + new NumberGroup35700("1000s", new List + { + "1000", "2000", "3000", "4000", "5000", + "6000", "7000", "8000", "9000", + }), + }; + + Content = collectionView; + } +} + +public class NumberGroup35700 : ObservableCollection +{ + public string Name { get; private set; } + + public NumberGroup35700(string name, List numbers) : base(numbers) + { + Name = name; + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs new file mode 100644 index 000000000000..23c0d5ae9e68 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue35700 : _IssuesUITest +{ + public Issue35700(TestDevice device) : base(device) { } + + public override string Issue => "Grouped CollectionView items not rendered properly on Android with GridItemsLayout"; + + [Test] + [Category(UITestCategories.CollectionView)] + public void GroupedCollectionViewGridLayoutRendersCorrectly() + { + // Wait for the CollectionView to fully load and render + App.WaitForElement("TestCollectionView"); + + // Verify the layout renders correctly: the first group's first row + // should have items uniformly sized and positioned across 5 columns. + // On Android with Span=5 and VerticalItemSpacing=10, there was a regression + // where the first row of the first group was incorrectly rendered. + VerifyScreenshot(); + } +} From 658f267749e3545605f13acef912ca7298eb9206 Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Fri, 5 Jun 2026 14:25:43 +0530 Subject: [PATCH 2/6] Fixed the item spacing issue --- .../Items/Android/SpacingItemDecoration.cs | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs index ca2525e79658..dc45cc66be52 100644 --- a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs +++ b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs @@ -84,10 +84,27 @@ public override void GetItemOffsets(ARect outRect, AView view, RecyclerView pare outRect.Top = VerticalOffset; // Remove spacing on the outer edges so spacing only appears between items. - // A linear layout is effectively span=1, so the same math works for both. - int rowCol = _span <= 1 ? position : position / _span; - int totalRowsCols = _span <= 1 ? itemCount : (itemCount + _span - 1) / _span; - int lastRowCol = totalRowsCols - 1; + int rowCol; + int lastRowCol; + + if (parent.GetLayoutManager() is GridLayoutManager gridLayoutManager) + { + // Use the GridLayoutManager's SpanSizeLookup to correctly compute which row (for + // vertical orientation) or column group (for horizontal orientation) this item belongs + // to. This correctly accounts for full-span items such as group headers/footers and + // list headers/footers, which would otherwise cause simple position / spanCount + // arithmetic to produce wrong row indices for the items that follow them. + var spanSizeLookup = gridLayoutManager.GetSpanSizeLookup(); + int spanCount = gridLayoutManager.SpanCount; + rowCol = spanSizeLookup.GetSpanGroupIndex(position, spanCount); + lastRowCol = spanSizeLookup.GetSpanGroupIndex(itemCount - 1, spanCount); + } + else + { + // Linear layout: each item occupies exactly one row/column. + rowCol = position; + lastRowCol = itemCount - 1; + } if (_orientation == ItemsLayoutOrientation.Vertical) { From cbaaeb24b57094c20d6d58e195f2c08ab015e1e3 Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:14:30 +0530 Subject: [PATCH 3/6] removed unwanted changes --- src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs | 2 +- .../tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs index 231a8a2a8b10..f6d49cbef26d 100644 --- a/src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs @@ -19,7 +19,7 @@ protected override void Init() ItemsLayout = new GridItemsLayout(ItemsLayoutOrientation.Vertical) { Span = 5, - VerticalItemSpacing = 10, + VerticalItemSpacing = 30, HorizontalItemSpacing = 10, }, GroupHeaderTemplate = new DataTemplate(() => diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs index 23c0d5ae9e68..525f10fbfbb9 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35700.cs @@ -14,13 +14,7 @@ public Issue35700(TestDevice device) : base(device) { } [Category(UITestCategories.CollectionView)] public void GroupedCollectionViewGridLayoutRendersCorrectly() { - // Wait for the CollectionView to fully load and render App.WaitForElement("TestCollectionView"); - - // Verify the layout renders correctly: the first group's first row - // should have items uniformly sized and positioned across 5 columns. - // On Android with Span=5 and VerticalItemSpacing=10, there was a regression - // where the first row of the first group was incorrectly rendered. VerifyScreenshot(); } } From ee5abdaa23a8bcbb8e2497f3d98b6a18e6804a5f Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Fri, 5 Jun 2026 16:11:04 +0530 Subject: [PATCH 4/6] Addressed the internal concerns --- .../Items/Android/SpacingItemDecoration.cs | 10 ++-------- ...CollectionViewGridLayoutRendersCorrectly.png | Bin 0 -> 19036 bytes 2 files changed, 2 insertions(+), 8 deletions(-) create mode 100644 src/Controls/tests/TestCases.Android.Tests/snapshots/android/GroupedCollectionViewGridLayoutRendersCorrectly.png diff --git a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs index dc45cc66be52..7abaeb2345a9 100644 --- a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs +++ b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs @@ -13,8 +13,6 @@ public class SpacingItemDecoration : RecyclerView.ItemDecoration public int VerticalOffset { get; } - int _span = 1; - ItemsLayoutOrientation _orientation; public SpacingItemDecoration(Context context, IItemsLayout itemsLayout) @@ -39,7 +37,6 @@ public SpacingItemDecoration(Context context, IItemsLayout itemsLayout) case GridItemsLayout gridItemsLayout: horizontalOffset = gridItemsLayout.HorizontalItemSpacing / 2.0; verticalOffset = gridItemsLayout.VerticalItemSpacing / 2.0; - _span = gridItemsLayout.Span; _orientation = gridItemsLayout.Orientation; break; case LinearItemsLayout listItemsLayout: @@ -89,11 +86,8 @@ public override void GetItemOffsets(ARect outRect, AView view, RecyclerView pare if (parent.GetLayoutManager() is GridLayoutManager gridLayoutManager) { - // Use the GridLayoutManager's SpanSizeLookup to correctly compute which row (for - // vertical orientation) or column group (for horizontal orientation) this item belongs - // to. This correctly accounts for full-span items such as group headers/footers and - // list headers/footers, which would otherwise cause simple position / spanCount - // arithmetic to produce wrong row indices for the items that follow them. + // Use SpanSizeLookup instead of position/spanCount so full-span items + // (group headers, footers, etc.) are accounted for when determining rows. var spanSizeLookup = gridLayoutManager.GetSpanSizeLookup(); int spanCount = gridLayoutManager.SpanCount; rowCol = spanSizeLookup.GetSpanGroupIndex(position, spanCount); diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/GroupedCollectionViewGridLayoutRendersCorrectly.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/GroupedCollectionViewGridLayoutRendersCorrectly.png new file mode 100644 index 0000000000000000000000000000000000000000..06a76bc22132e6ad6be0079d96c8ca8d2798c8ed GIT binary patch literal 19036 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 Y)zvE Date: Fri, 5 Jun 2026 18:26:09 +0530 Subject: [PATCH 5/6] Address the internal fix concern --- .../Handlers/Items/Android/SpacingItemDecoration.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs index 7abaeb2345a9..4f7d9b679dd4 100644 --- a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs +++ b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs @@ -15,6 +15,9 @@ public class SpacingItemDecoration : RecyclerView.ItemDecoration ItemsLayoutOrientation _orientation; + int _cachedLastRowCol = -1; + int _cachedItemCount = -1; + public SpacingItemDecoration(Context context, IItemsLayout itemsLayout) { // The original "SpacingItemDecoration" applied spacing based on an item's current span index. @@ -91,7 +94,14 @@ public override void GetItemOffsets(ARect outRect, AView view, RecyclerView pare var spanSizeLookup = gridLayoutManager.GetSpanSizeLookup(); int spanCount = gridLayoutManager.SpanCount; rowCol = spanSizeLookup.GetSpanGroupIndex(position, spanCount); - lastRowCol = spanSizeLookup.GetSpanGroupIndex(itemCount - 1, spanCount); + + if (_cachedItemCount != itemCount) + { + _cachedLastRowCol = spanSizeLookup.GetSpanGroupIndex(itemCount - 1, spanCount); + _cachedItemCount = itemCount; + } + + lastRowCol = _cachedLastRowCol; } else { From afdd6e02d2c8d9aae7bb25d2dc6d7846719e7d14 Mon Sep 17 00:00:00 2001 From: Shalini-Ashokan <102292178+Shalini-Ashokan@users.noreply.github.com> Date: Tue, 9 Jun 2026 18:32:54 +0530 Subject: [PATCH 6/6] Addressed the AI summary --- .../Items/Android/GridLayoutSpanSizeLookup.cs | 3 +++ .../Handlers/Items/Android/SpacingItemDecoration.cs | 12 +----------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/Controls/src/Core/Handlers/Items/Android/GridLayoutSpanSizeLookup.cs b/src/Controls/src/Core/Handlers/Items/Android/GridLayoutSpanSizeLookup.cs index 90ed595e41f4..dd769fe734bc 100644 --- a/src/Controls/src/Core/Handlers/Items/Android/GridLayoutSpanSizeLookup.cs +++ b/src/Controls/src/Core/Handlers/Items/Android/GridLayoutSpanSizeLookup.cs @@ -12,6 +12,9 @@ public GridLayoutSpanSizeLookup(GridItemsLayout gridItemsLayout, RecyclerView re { _gridItemsLayout = gridItemsLayout; _recyclerView = recyclerView; + + SpanIndexCacheEnabled = true; + SpanGroupIndexCacheEnabled = true; } public override int GetSpanSize(int position) diff --git a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs index 4f7d9b679dd4..7abaeb2345a9 100644 --- a/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs +++ b/src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs @@ -15,9 +15,6 @@ public class SpacingItemDecoration : RecyclerView.ItemDecoration ItemsLayoutOrientation _orientation; - int _cachedLastRowCol = -1; - int _cachedItemCount = -1; - public SpacingItemDecoration(Context context, IItemsLayout itemsLayout) { // The original "SpacingItemDecoration" applied spacing based on an item's current span index. @@ -94,14 +91,7 @@ public override void GetItemOffsets(ARect outRect, AView view, RecyclerView pare var spanSizeLookup = gridLayoutManager.GetSpanSizeLookup(); int spanCount = gridLayoutManager.SpanCount; rowCol = spanSizeLookup.GetSpanGroupIndex(position, spanCount); - - if (_cachedItemCount != itemCount) - { - _cachedLastRowCol = spanSizeLookup.GetSpanGroupIndex(itemCount - 1, spanCount); - _cachedItemCount = itemCount; - } - - lastRowCol = _cachedLastRowCol; + lastRowCol = spanSizeLookup.GetSpanGroupIndex(itemCount - 1, spanCount); } else {