Skip to content

[iOS, MacCatalyst] Fix CollectionView grid spacing updates for first row and column#34598

Open
KarthikRajaKalaimani wants to merge 5 commits intodotnet:mainfrom
KarthikRajaKalaimani:fix-34257-iOS
Open

[iOS, MacCatalyst] Fix CollectionView grid spacing updates for first row and column#34598
KarthikRajaKalaimani wants to merge 5 commits intodotnet:mainfrom
KarthikRajaKalaimani:fix-34257-iOS

Conversation

@KarthikRajaKalaimani
Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details:

Horizontalspacing / Verticalspacing is not not applied to the first column in GridItemLayout using CollectionView on iOS,Mac and Android platform.

Root Cause:

The grid spacing was not being distributed symmetrically across the active layout implementations, so edge items did not fully participate when spacing changed at runtime. On iOS and MacCatalyst, the active Items2 compositional layout path handled spacing in a way that visually created gaps but did not cause the first column and first row to update consistently with the rest of the grid.

Description of Change:

  • On iOS/MacCatalyst, the fix in LayoutFactory2.cs keeps the existing compositional grid item sizing (FractionalWidth(1f / span) for vertical grids and FractionalHeight(1f / span) for horizontal grids), but changes how spacing is applied. Instead of relying on group.InterItemSpacing, the fix computes half of the requested horizontal and vertical spacing and applies that half-spacing through item.ContentInsets so each item contributes to the gap. It then sets group.InterItemSpacing to 0, keeps section.InterGroupSpacing for spacing between rows or columns, and adds matching half-spacing to section.ContentInsets. This makes the first row/column participate when spacing changes, which fixes the issue where only later rows or columns visually updated.

**Tested the behavior in the following platforms: **

  • Android
  • Windows
  • iOS
  • Mac

Reference:

N/A

Issues Fixed:

Fixes #34257

Screenshots

Before After
Screen.Recording.2026-03-18.at.4.25.45.PM.mov
Screen.Recording.2026-03-18.at.4.21.12.PM.mov

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 23, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34598

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34598"

@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Mar 23, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @@KarthikRajaKalaimani! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Mar 23, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review March 24, 2026 06:56
Copilot AI review requested due to automatic review settings March 24, 2026 06:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the iOS/MacCatalyst Items2 CollectionView compositional grid layout to ensure spacing changes at runtime correctly affect the first row/column in a grid.

Changes:

  • Apply half-spacing via NSCollectionLayoutItem.ContentInsets to distribute inter-item spacing across items.
  • Set group.InterItemSpacing to 0 and rely on item/section insets plus section.InterGroupSpacing to control spacing.

Comment on lines +160 to +200
var halfHorizontalSpacing = new NFloat(horizontalItemSpacing / 2d);
var halfVerticalSpacing = new NFloat(verticalItemSpacing / 2d);

if (scrollDirection == UICollectionViewScrollDirection.Vertical && horizontalItemSpacing > 0)
{
item.ContentInsets = new NSDirectionalEdgeInsets(0, halfHorizontalSpacing, 0, halfHorizontalSpacing);
}
else if (scrollDirection == UICollectionViewScrollDirection.Horizontal && verticalItemSpacing > 0)
{
item.ContentInsets = new NSDirectionalEdgeInsets(halfVerticalSpacing, 0, halfVerticalSpacing, 0);
}
// Each group of items (for grouped collections) has a size
var groupSize = NSCollectionLayoutSize.Create(groupWidth, groupHeight);

// Create the group
// If vertical list, we want the group to layout horizontally (eg: grid columns go left to right)
// for horizontal list, we want to lay grid rows out vertically
// For simple lists it doesn't matter so much since the items span the entire width or height
var group = scrollDirection == UICollectionViewScrollDirection.Vertical
? NSCollectionLayoutGroup.CreateHorizontal(groupSize, item, columns)
: NSCollectionLayoutGroup.CreateVertical(groupSize, item, columns);

if (scrollDirection == UICollectionViewScrollDirection.Vertical)
group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(new NFloat(horizontalItemSpacing));
else
group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(new NFloat(verticalItemSpacing));

group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(0);
// Create our section layout
var section = NSCollectionLayoutSection.Create(group: group);

if (scrollDirection == UICollectionViewScrollDirection.Vertical)
{
section.InterGroupSpacing = new NFloat(verticalItemSpacing);
if (verticalItemSpacing > 0)
{
section.ContentInsets = new NSDirectionalEdgeInsets(halfVerticalSpacing, 0, halfVerticalSpacing, 0);
}
}
else
{
section.InterGroupSpacing = new NFloat(horizontalItemSpacing);
if (horizontalItemSpacing > 0)
{
section.ContentInsets = new NSDirectionalEdgeInsets(0, halfHorizontalSpacing, 0, halfHorizontalSpacing);
}
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Using item/section ContentInsets to distribute spacing introduces outer padding around the grid (first/last row/column get half the spacing). GridItemsLayout’s HorizontalItemSpacing/VerticalItemSpacing are documented as spacing between items, and the previous implementation (group.InterItemSpacing/section.InterGroupSpacing) did not add edge spacing. Consider compensating for the half-insets (e.g., offset section insets negatively on the corresponding edges) so the requested spacing exists only between items, not between items and the CollectionView edges.

Copilot uses AI. Check for mistakes.
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 27, 2026

🚦 Gate - Test Before and After Fix

📊 Expand Full Gate74d81b2 · removed the android fix

Gate Result: ✅ PASSED

Platform: IOS · Base: main · Merge base: 720a9d4a

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue34257 Issue34257 ✅ FAIL — 199s ✅ PASS — 85s
🔴 Without fix — 🖥️ Issue34257: FAIL ✅ · 199s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 1.5 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 1.5 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 8.52 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 8.67 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 8.68 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 8.68 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 8.67 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 8.69 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 8.7 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 8.69 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 8.7 sec).
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:01:36.61
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 1.05 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 1.05 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 1.05 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 1.08 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 1.19 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 1.31 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.55 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 1.56 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 1.57 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 1.73 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 1.7 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 2.32 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj (in 3.42 sec).
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.04]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.13]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 3/30/2026 7:12:29 AM FixtureSetup for Issue34257(iOS)
>>>>> 3/30/2026 7:12:33 AM UpdatingHorizontalSpacingShouldResizeBothColumns Start
>>>>> 3/30/2026 7:12:34 AM UpdatingHorizontalSpacingShouldResizeBothColumns Stop
>>>>> 3/30/2026 7:12:34 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
>>>>> 3/30/2026 7:12:34 AM UpdatingVerticalSpacingShouldResizeBothRows Start
  Failed UpdatingHorizontalSpacingShouldResizeBothColumns [1 s]
  Error Message:
     Expected the first column to move
Assert.That(firstColumnBefore.X, Is.Not.EqualTo(firstColumnAfter.X))
  Expected: not equal to 17
  But was:  17

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue34257.UpdatingHorizontalSpacingShouldResizeBothColumns() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34257.cs:line 24

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue34257.UpdatingHorizontalSpacingShouldResizeBothColumns() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34257.cs:line 24


>>>>> 3/30/2026 7:12:35 AM UpdatingVerticalSpacingShouldResizeBothRows Stop
>>>>> 3/30/2026 7:12:35 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed UpdatingVerticalSpacingShouldResizeBothRows [1 s]
  Error Message:
     Expected the first row to move
Assert.That(firstColumnBefore.Y, Is.Not.EqualTo(firstColumnAfter.Y))
  Expected: not equal to 227
  But was:  227

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue34257.UpdatingVerticalSpacingShouldResizeBothRows() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34257.cs:line 35

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue34257.UpdatingVerticalSpacingShouldResizeBothRows() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34257.cs:line 35


NUnit Adapter 4.5.0.0: Test execution complete

Test Run Failed.
Total tests: 2
     Failed: 2
 Total time: 58.8042 Seconds

🟢 With fix — 🖥️ Issue34257: PASS ✅ · 85s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 323 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 337 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 338 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 371 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 382 ms).
  6 of 11 projects are up-to-date for restore.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:43.01
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 344 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 356 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 353 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 364 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 381 ms).
  8 of 13 projects are up-to-date for restore.
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13687627
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.04]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.12]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 3/30/2026 7:13:55 AM FixtureSetup for Issue34257(iOS)
>>>>> 3/30/2026 7:13:59 AM UpdatingHorizontalSpacingShouldResizeBothColumns Start
>>>>> 3/30/2026 7:14:00 AM UpdatingHorizontalSpacingShouldResizeBothColumns Stop
>>>>> 3/30/2026 7:14:00 AM UpdatingVerticalSpacingShouldResizeBothRows Start
  Passed UpdatingHorizontalSpacingShouldResizeBothColumns [811 ms]
>>>>> 3/30/2026 7:14:01 AM UpdatingVerticalSpacingShouldResizeBothRows Stop
  Passed UpdatingVerticalSpacingShouldResizeBothRows [1 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 2
     Passed: 2
 Total time: 17.8053 Seconds

📁 Fix files reverted (2 files)
  • eng/pipelines/ci-copilot.yml
  • src/Controls/src/Core/Handlers/Items2/iOS/LayoutFactory2.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 27, 2026

🤖 AI Summary

📊 Expand Full Review74d81b2 · removed the android fix
🔍 Pre-Flight — Context & Validation

Issue: #34257 - [MAUI] CollectionView grid spacing only updates second column on iOS/MacCatalyst
PR: #34598 - [iOS, MacCatalyst] Fix CollectionView grid spacing updates for first row and column
Platforms Affected: iOS, MacCatalyst (fix in Items2 path only)
Files Changed: 1 implementation, 2 test

Key Findings

  • Bug: When HorizontalItemSpacing/VerticalItemSpacing is changed at runtime on a GridItemsLayout CollectionView, only the 2nd column (vertical grid) or 2nd row (horizontal grid) visually updates — the first column/row does not move.
  • Root cause: In LayoutFactory2.cs, the old approach used group.InterItemSpacing which only inserts gaps between items within a group. It doesn't shift the first item relative to the group edge, so the first column stays flush.
  • Fix approach: Replace group.InterItemSpacing with item.ContentInsets (half-spacing on each side per item), set group.InterItemSpacing = 0, and add matching half-spacing to section.ContentInsets so the first/last row or column participates in spacing updates.
  • ⚠️ Copilot reviewer flag: section.ContentInsets adds outer padding around the entire grid (first and last row/column get half the inter-item spacing from the CollectionView edges). The documented semantics of HorizontalItemSpacing/VerticalItemSpacing is spacing between items only — edge items should not receive edge padding from this property.
  • The test only validates position movement (X/Y changed), not the exact spacing values or edge padding behavior.
  • Gate passed on iOS: both tests fail without fix, pass with fix.
  • PR labels include s/agent-review-incomplete — prior agent review was incomplete.
  • PR has merge conflicts with target branch (reported by MauiBot multiple times).

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34598 Replace group.InterItemSpacing with item.ContentInsets (half-spacing) + section.ContentInsets ✅ PASSED (Gate) LayoutFactory2.cs Adds edge padding — see Copilot review comment

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) + (half-spacing each side), zero InterItemSpacing/InterGroupSpacing PASS LayoutFactory2.cs No outer edge cleanest semantics
2 try-fix (claude-sonnet-4.6) (half-spacing) + absolute item widths computed from container + original InterItemSpacing PASS LayoutFactory2.cs More complex; absolute widths from environment
3 try-fix (gpt-5.3-codex) NSCollectionLayoutSpacing.CreateFlexible for `group. FAIL LayoutFactory2.cs Flexible spacing alone insufficient InterItemSpacing`
4 try-fix (gpt-5.4, gemini unavailable) Force layout rebuild in handler on spacing FAIL ItemsViewController2.cs Confirms layout IS rebuilt; bug is in LayoutFactory2 geometry change
5 try-fix (claude-sonnet-4.6, cross-poll) (half-spacing) + negative to cancel outer edge; only for same-direction spacing PASS LayoutFactory2.cs Partially addresses reviewer concern; still needs section.ContentInsets for vertical gap
PR PR #34598 (half-spacing) + + PASSED (Gate) LayoutFactory2.cs Adds outer edge padding to grid reviewer flagged

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 Yes NSCollectionLayoutGroup.CreateCustom with explicit CGRect frames
ran as Attempt 5
gpt-5.3-codex 2 Yes VisibleItemsInvalidationHandler post-process frames at runtime
gpt-5.4 2 Yes Explicit subitems array with asymmetric per-item insets
claude-opus-4.6 3 NO NEW IDEAS Design space well-covered
claude-sonnet-4.6 3 CreateCustom (already noted round 2) Same idea as round not materially new
gpt-5.3-codex 3 CreateCustom variation Same concept as round more complex, no gain
gpt-5.4 3 Explicit subitems variation Variation of round 2 similar complexity

Exhausted: round 3 produced no new distinct approaches; all models converging on already-noted ideasYes
Selected Fix: Attempt 1 ( Reasons: (1) no outer edge padding at all (cleanest semantics, fully matches HorizontalItemSpacing/VerticalItemSpacing documentation as between-item spacing only); (2) simplest conceptual change; (3) directly fixes the PR reviewer's concern without adding section.ContentInsets; (4) single consistent mechanism (EdgeSpacing) for both directions; (5) fewer lines than Attempt 5 which still requires section.ContentInsets for same-direction spacingEdgeSpacing)


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #34257, iOS/MacCatalyst, 1 fix file + 2 test files
Gate ✅ PASSED iOS — both tests fail without fix, pass with fix
Try-Fix ✅ COMPLETE 5 attempts, 3 passing alternatives found
Report ✅ COMPLETE

Summary

PR #34598 correctly fixes the CollectionView grid spacing bug on iOS/MacCatalyst where only the 2nd column/row visually updates when HorizontalItemSpacing/VerticalItemSpacing changes at runtime. The gate passed and the tests are well-designed. However, the PR's implementation has a documented semantic issue flagged by the Copilot code reviewer, and Try-Fix exploration found a simpler alternative that avoids it. The recommendation is REQUEST CHANGES to adopt the better fix.

Additionally, the PR has active merge conflicts with main that must be resolved before merge.

Root Cause

CreateGridLayout in LayoutFactory2.cs (Items2 iOS/MacCatalyst path) used group.InterItemSpacing which only inserts gaps between items within a group. The first item in each group always starts at offset 0 relative to the group origin — it is never repositioned when spacing changes. Only subsequent items shift (receiving a gap before them), leaving the first column/row visually frozen at runtime spacing updates.

Fix Quality

PR's fix (item.ContentInsets + section.ContentInsets):

  • ✅ Fixes the bug — gate passed
  • ✅ Tests are well-structured with descriptive AutomationIds
  • ⚠️ Semantic issue: section.ContentInsets adds outer padding around the entire grid — first and last row/column get half the inter-item spacing between them and the CollectionView boundary. HorizontalItemSpacing/VerticalItemSpacing are documented as spacing between items only; edge items should not receive insets from this property.
  • ⚠️ This was explicitly flagged by the Copilot code reviewer in PR inline comments.
  • ⚠️ PR has merge conflicts with main.

Better alternative found (Attempt 1 — item.EdgeSpacing + group.EdgeSpacing):

  • ✅ Fixes the bug — tests pass
  • ✅ No outer edge padding — NSCollectionLayoutEdgeSpacing shifts the item/group frame position itself (outside the frame), so adjacent items' frames shift together symmetrically with no boundary accumulation
  • ✅ Simpler: sets group.InterItemSpacing = 0 and section.InterGroupSpacing = 0, no section.ContentInsets needed
  • ✅ Directly addresses the reviewer's concern without section.ContentInsets
  • ✅ Single consistent mechanism for both cross-axis and scroll-axis spacing

Suggested fix diff for LayoutFactory2.cs:

+       var halfHorizontalSpacing = new NFloat(horizontalItemSpacing / 2d);
+       var halfVerticalSpacing = new NFloat(verticalItemSpacing / 2d);
+       var zeroSpacing = NSCollectionLayoutSpacing.CreateFixed(0);
+
+       if (scrollDirection == UICollectionViewScrollDirection.Vertical && horizontalItemSpacing > 0)
+           item.EdgeSpacing = NSCollectionLayoutEdgeSpacing.Create(
+               leading: NSCollectionLayoutSpacing.CreateFixed(halfHorizontalSpacing),
+               top: zeroSpacing,
+               trailing: NSCollectionLayoutSpacing.CreateFixed(halfHorizontalSpacing),
+               bottom: zeroSpacing);
+       else if (scrollDirection == UICollectionViewScrollDirection.Horizontal && verticalItemSpacing > 0)
+           item.EdgeSpacing = NSCollectionLayoutEdgeSpacing.Create(
+               leading: zeroSpacing,
+               top: NSCollectionLayoutSpacing.CreateFixed(halfVerticalSpacing),
+               trailing: zeroSpacing,
+               bottom: NSCollectionLayoutSpacing.CreateFixed(halfVerticalSpacing));
+
+       // ...after group creation:
+       group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(0);
+       if (scrollDirection == Vertical && verticalItemSpacing > 0)
+           group.EdgeSpacing = NSCollectionLayoutEdgeSpacing.Create(zeroSpacing,
+               NSCollectionLayoutSpacing.CreateFixed(halfVerticalSpacing), zeroSpacing,
+               NSCollectionLayoutSpacing.CreateFixed(halfVerticalSpacing));
+       else if (scrollDirection == Horizontal && horizontalItemSpacing > 0)
+           group.EdgeSpacing = NSCollectionLayoutEdgeSpacing.Create(
+               NSCollectionLayoutSpacing.CreateFixed(halfHorizontalSpacing), zeroSpacing,
+               NSCollectionLayoutSpacing.CreateFixed(halfHorizontalSpacing), zeroSpacing);
+
-       if (scrollDirection == UICollectionViewScrollDirection.Vertical)
-           group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(new NFloat(horizontalItemSpacing));
-       else
-           group.InterItemSpacing = NSCollectionLayoutSpacing.CreateFixed(new NFloat(verticalItemSpacing));
        var section = NSCollectionLayoutSection.Create(group: group);
-       if (scrollDirection == UICollectionViewScrollDirection.Vertical)
-           section.InterGroupSpacing = new NFloat(verticalItemSpacing);
-       else
-           section.InterGroupSpacing = new NFloat(horizontalItemSpacing);
+       // (remove section.InterGroupSpacing — group.EdgeSpacing handles scroll-axis gaps)

Test Assessment

  • Issue34257.cs (HostApp): Well-structured C# page with AutomationIds, 4 items in 2-column grid, buttons to apply horizontal/vertical spacing separately
  • Issue34257.cs (SharedTests): Two focused tests — one for each spacing direction — using position comparison (X / Y changed) rather than screenshot comparison (avoids flakiness)
  • [Category(UITestCategories.CollectionView)] — correct category
  • ✅ Inherits _IssuesUITest, standard pattern
  • PlatformAffected.Android | PlatformAffected.iOS | PlatformAffected.macOS — but PR only fixes iOS/MacCatalyst (Items2 path). Android is unresolved (issue [MAUI] I2_Vertical grid for horizontal Item Spacing and Vertical Item Spacing - horizontally updating the spacing only applies to the second column #34257 affects it too).

Action Items for Author

  1. Resolve merge conflicts with main
  2. Replace spacing approach with item.EdgeSpacing + group.EdgeSpacing to avoid outer edge padding (see diff above), or confirm with the reviewer whether the section.ContentInsets behavior is acceptable
  3. Android: Issue [MAUI] I2_Vertical grid for horizontal Item Spacing and Vertical Item Spacing - horizontally updating the spacing only applies to the second column #34257 is labeled platform/android — consider noting in PR that Android fix is deferred or tracked separately (the PR currently only fixes iOS/MacCatalyst Items2 path)
  4. Test for zero-spacing reset: Consider adding a test that verifies spacing resets to 0 after being non-zero (ensure content insets/edge spacing are cleared when spacing = 0)

@MauiBot MauiBot added s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 27, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 27, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

3 similar comments
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 27, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 27, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 28, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you resolve conflicts?

@kubaflo kubaflo changed the base branch from inflight/current to main March 28, 2026 17:26
…net#34527)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

Horizontalspacing / Verticalspacing is not not applied to the first
column in GridItemLayout using CollectionView on Android platform.

The grid spacing was not being distributed symmetrically across the
active layout implementations, so edge items did not fully participate
when spacing changed at runtime.

- On Android, the fix in MauiRecyclerView.cs changes how RecyclerView
padding is handled for GridItemsLayout. Android was already using
SpacingItemDecoration, which applies half-spacing on all four sides of
each item. Previously, negative RecyclerView padding canceled that
spacing at the control edges. The branch keeps that negative-padding
behavior for non-grid layouts, but disables it for GridItemsLayout,
allowing the grid’s half-spacing to remain visible at the outer
perimeter. This makes the first row and first column visually respond
when spacing changes, but it also changes the grid behavior from spacing
only between items to spacing around the outside edges as well.

**Tested the behavior in the following platforms:**

- [x] Android
- [x] Windows
- [ ] iOS
- [ ] Mac

N/A

Fixes  dotnet#34257

| Before  | After  |
|---------|--------|
| <Video
src="https://github.com/user-attachments/assets/578dda69-1d60-474c-a6d8-23b3f9d29a50"
Width="300" Height="600"> | <Video
src="https://github.com/user-attachments/assets/7f3826e6-5922-4b6f-a6b9-de581b7db6c3"
Width="300" Height="600"> |
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues and removed s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) labels Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-collectionview CollectionView, CarouselView, IndicatorView community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/ios platform/macos macOS / Mac Catalyst s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[MAUI] I2_Vertical grid for horizontal Item Spacing and Vertical Item Spacing - horizontally updating the spacing only applies to the second column

6 participants