Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -259,6 +259,7 @@ static WStyle GetItemContainerStyle(GridItemsLayout layout)
style.Setters.Add(new WSetter(FrameworkElement.MarginProperty, margin));
style.Setters.Add(new WSetter(Control.PaddingProperty, WinUIHelpers.CreateThickness(0)));
style.Setters.Add(new WSetter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
style.Setters.Add(new WSetter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Stretch));

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.

🔍 AI-Generated Review (multi-model)

[major] Cross-Platform Behavioral Consistency / Regression PreventionVerticalContentAlignment=Stretch is added unconditionally in GetItemContainerStyle(GridItemsLayout), which builds the GridViewItem style for every Windows GridItemsLayout (grouped and non-grouped alike) — there is no IsGrouped check anywhere in this file. The regression test added by this PR only covers a grouped grid, so the adjacent non-grouped scenario is unverified: a non-grouped CollectionView/GridItemsLayout with items of varying content height per row will now have those items force-stretched vertically to fill the row height instead of the previous top-aligned behavior, changing the rendered appearance for existing non-grouped grids. Consider scoping the stretch to grouped grids only (e.g. applying it from the grouped-items handler path, or gating the setter on ItemsView.IsGrouped) so non-grouped Windows grids keep their prior vertical alignment.


return style;
}
Expand Down
79 changes: 54 additions & 25 deletions src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,35 @@ static NSCollectionLayoutBoundarySupplementaryItem[] CreateSupplementaryItems(La
return [];
}

static void ApplyHeaderFooterBoundarySpacing(NSCollectionLayoutSection section, UICollectionViewScrollDirection scrollDirection, double verticalSpacing, double horizontalSpacing, bool hasHeader, bool hasFooter, bool applySpacing)
{
if (!applySpacing)
{
return;
}

if (scrollDirection == UICollectionViewScrollDirection.Vertical)
{
var topInset = hasHeader ? new NFloat(verticalSpacing) : new NFloat(0);
var bottomInset = hasFooter ? new NFloat(verticalSpacing) : new NFloat(0);

if (topInset > 0 || bottomInset > 0)
{
section.ContentInsets = new NSDirectionalEdgeInsets(topInset, 0, bottomInset, 0);
}
}
else
{
var leadingInset = hasHeader ? new NFloat(horizontalSpacing) : new NFloat(0);
var trailingInset = hasFooter ? new NFloat(horizontalSpacing) : new NFloat(0);

if (leadingInset > 0 || trailingInset > 0)
{
section.ContentInsets = new NSDirectionalEdgeInsets(0, leadingInset, 0, trailingInset);
}
}
}

static UICollectionViewLayout CreateListLayout(UICollectionViewScrollDirection scrollDirection, LayoutGroupingInfo groupingInfo, LayoutHeaderFooterInfo layoutHeaderFooterInfo, LayoutSnapInfo snapInfo, NSCollectionLayoutDimension itemWidth, NSCollectionLayoutDimension itemHeight, NSCollectionLayoutDimension groupWidth, NSCollectionLayoutDimension groupHeight, double itemSpacing, Func<Thickness>? peekAreaInsetsFunc, ItemsLayout itemsLayout)
{
var layoutConfiguration = new UICollectionViewCompositionalLayoutConfiguration();
Expand Down Expand Up @@ -145,31 +174,14 @@ static UICollectionViewLayout CreateListLayout(UICollectionViewScrollDirection s
// For grouped sections with a group header/footer, add content insets to create
// the gap between the header/footer supplementary item and the first/last item.
// InterSectionSpacing (set on layoutConfiguration above) handles the gap between sections.
if (groupingInfo.IsGrouped && itemSpacing > 0)
{
if (scrollDirection == UICollectionViewScrollDirection.Horizontal)
{
var leadingInset = groupingInfo.HasHeader ? new NFloat(itemSpacing) : new NFloat(0);
var trailingInset = groupingInfo.HasFooter ? new NFloat(itemSpacing) : new NFloat(0);

if (leadingInset > 0 || trailingInset > 0)
{
section.ContentInsets = new NSDirectionalEdgeInsets(0, leadingInset, 0, trailingInset);
}
}
else
{
// Vertical: top inset creates gap between header and first item,
// bottom inset creates gap between last item and footer.
var topInset = groupingInfo.HasHeader ? new NFloat(itemSpacing) : new NFloat(0);
var bottomInset = groupingInfo.HasFooter ? new NFloat(itemSpacing) : new NFloat(0);

if (topInset > 0 || bottomInset > 0)
{
section.ContentInsets = new NSDirectionalEdgeInsets(topInset, 0, bottomInset, 0);
}
}
}
ApplyHeaderFooterBoundarySpacing(
section,
scrollDirection,
itemSpacing,
itemSpacing,
groupingInfo.HasHeader,
groupingInfo.HasFooter,
groupingInfo.IsGrouped && itemSpacing > 0);

// Create header and footer for group
section.BoundarySupplementaryItems = CreateSupplementaryItems(
Expand All @@ -192,6 +204,15 @@ static UICollectionViewLayout CreateGridLayout(UICollectionViewScrollDirection s
var layoutConfiguration = new UICollectionViewCompositionalLayoutConfiguration();
layoutConfiguration.ScrollDirection = scrollDirection;

var mainAxisSpacing = scrollDirection == UICollectionViewScrollDirection.Vertical
? verticalItemSpacing
: horizontalItemSpacing;

if (groupingInfo.IsGrouped && mainAxisSpacing > 0)
{
layoutConfiguration.InterSectionSpacing = new NFloat(mainAxisSpacing);
}

var layout = new CustomUICollectionViewCompositionalLayout(snapInfo, groupingInfo, headerFooterInfo, (sectionIndex, environment) =>
{
// Each item has a size
Expand Down Expand Up @@ -235,6 +256,14 @@ static UICollectionViewLayout CreateGridLayout(UICollectionViewScrollDirection s
section.InterGroupSpacing = new NFloat(horizontalItemSpacing);
}

ApplyHeaderFooterBoundarySpacing(
section,
scrollDirection,
verticalItemSpacing,
horizontalItemSpacing,
groupingInfo.HasHeader,
groupingInfo.HasFooter,
groupingInfo.IsGrouped && mainAxisSpacing > 0);

section.BoundarySupplementaryItems = CreateSupplementaryItems(
groupingInfo,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/Controls/tests/TestCases.HostApp/Issues/Issue35700.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 35700,
Comment thread
Shalini-Ashokan marked this conversation as resolved.
Comment thread
Shalini-Ashokan marked this conversation as resolved.
"Grouped CollectionView items not rendered properly on Android with GridItemsLayout",
Comment thread
Shalini-Ashokan marked this conversation as resolved.
PlatformAffected.Android)]
PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.macOS | PlatformAffected.UWP)]
public class Issue35700 : TestContentPage
{
protected override void Init()
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading