Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ public class SpacingItemDecoration : RecyclerView.ItemDecoration

public int VerticalOffset { get; }

int _span = 1;

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.
Expand All @@ -39,7 +40,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:
Expand Down Expand Up @@ -84,10 +84,31 @@ 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 SpanSizeLookup instead of position/spanCount so full-span items
// (group headers, footers, etc.) are accounted for when determining rows.
var spanSizeLookup = gridLayoutManager.GetSpanSizeLookup();
Comment thread
Shalini-Ashokan marked this conversation as resolved.
int spanCount = gridLayoutManager.SpanCount;
rowCol = spanSizeLookup.GetSpanGroupIndex(position, spanCount);

if (_cachedItemCount != itemCount)
Comment thread
Shalini-Ashokan marked this conversation as resolved.
Outdated
{
_cachedLastRowCol = spanSizeLookup.GetSpanGroupIndex(itemCount - 1, spanCount);
_cachedItemCount = itemCount;
}

lastRowCol = _cachedLastRowCol;
}
else
{
// Linear layout: each item occupies exactly one row/column.
rowCol = position;
lastRowCol = itemCount - 1;
}

if (_orientation == ItemsLayoutOrientation.Vertical)
{
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 91 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs
Original file line number Diff line number Diff line change
@@ -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 = 30,
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<NumberGroup35700>
{
new NumberGroup35700("100s", new List<string>
{
"100", "200", "300", "400", "500",
"600", "700", "800", "900",
}),
new NumberGroup35700("1000s", new List<string>
{
"1000", "2000", "3000", "4000", "5000",
"6000", "7000", "8000", "9000",
}),
};

Content = collectionView;
}
}

public class NumberGroup35700 : ObservableCollection<string>
{
public string Name { get; private set; }

public NumberGroup35700(string name, List<string> numbers) : base(numbers)
{
Name = name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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()
{
App.WaitForElement("TestCollectionView");
VerifyScreenshot();
Comment thread
Shalini-Ashokan marked this conversation as resolved.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[major] Regression Prevention and Test Coverage - This shared screenshot test runs on all UI test platforms, but the PR only adds an Android snapshot baseline and the issue page is marked Android-only. Non-Android runs can still execute this test and fail at VerifyScreenshot() due to missing iOS/Mac/Windows baselines. Please either guard this test to Android only or add baselines for every platform where it should run.

}
}
Loading