[iOS/macOS] CollectionView: Fix FlowDirection not working on EmptyView#32674
[iOS/macOS] CollectionView: Fix FlowDirection not working on EmptyView#32674kubaflo merged 13 commits intodotnet:inflight/currentfrom
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR fixes FlowDirection not working on EmptyView in CollectionView for iOS and macOS platforms by replacing the old transform-based RTL handling with proper FlowDirection propagation through the MAUI framework.
Key changes:
- Removed legacy transform-based RTL flip logic that was causing incorrect visual behavior
- Implemented proper FlowDirection propagation using
UpdateFlowDirection()for View-based and DataTemplate-based EmptyViews - Centered text alignment for string-based EmptyViews (UILabel) to ensure consistent cross-platform behavior
- Added UI test with screenshot verification to validate FlowDirection behavior changes
Reviewed Changes
Copilot reviewed 4 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32404.cs |
NUnit UI test implementation with screenshot verification for FlowDirection toggle behavior |
src/Controls/tests/TestCases.HostApp/Issues/Issue32404.cs |
Test page with three EmptyView types (string, View, DataTemplate) to validate fix |
src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs |
iOS platform code update removing transform-based RTL logic and using UpdateFlowDirection |
src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs |
iOS platform code update (same changes as Items2) for consistency |
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlowDirectionShouldWorkOnEmptyView_RightToLeft.png |
Screenshot baseline for RTL FlowDirection |
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlowDirectionShouldWorkOnEmptyView_LeftToRight.png |
Screenshot baseline for LTR FlowDirection |
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
18935dc to
2dc2cac
Compare
There was a problem hiding this comment.
The core approach is good (using UpdateFlowDirection() instead of transforms), but there are concerns about:
- Complete FlowDirection support for string-based EmptyViews
- Missing macOS test snapshots
- Inconsistency between PR scope (iOS/macOS only) and issue description (includes Android)
|
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
MauiBot
left a comment
There was a problem hiding this comment.
🤖 Automated review — alternative fix proposed
The expert-reviewer evaluation compared the PR fix against #2 automatically generated candidates and selected try-fix-2 as the strongest fix.
Why: try-fix-2 is the winning candidate: it preserves the PR's correct core approach (UpdateFlowDirection instead of transform flip, superview placement in Items2) while fixing the critical FlowDirection.MatchParent regression identified by code review — the UILabel path now uses a switch expression with EffectiveUserInterfaceLayoutDirection as fallback, correctly handling the default case where system-locale RTL users have not explicitly set FlowDirection. All four try-fix candidates passed tests; the PR itself failed the gate; try-fix-2 is the most targeted, minimal fix that directly addresses the highest-severity code review finding.
Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.
Candidate diff (`try-fix-2`)
diff --git a/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs b/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs
index 04d41a5607..b0f2b6e4d5 100644
--- a/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs
+++ b/src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs
@@ -444,10 +444,20 @@ namespace Microsoft.Maui.Controls.Handlers.Items
if (ItemsView.Handler.PlatformView is UIView itemsView)
{
itemsView.UpdateFlowDirection(ItemsView);
+ // Items/ only iterates logical children when an ItemTemplate is set; the else branch
+ // handles DefaultCell labels directly and does not iterate logical children, so the skip
+ // below is only needed inside the ItemTemplate branch (not in the else branch).
if (ItemsView.ItemTemplate is not null)
{
foreach (var child in ItemsView.LogicalChildrenInternal)
{
+ // Skip the empty view element — its flow direction is handled
+ // separately in AlignEmptyView to avoid double application
+ if (child == _emptyViewFormsElement)
+ {
+ continue;
+ }
+
if (child is VisualElement ve && ve.Handler?.PlatformView is UIView view)
{
view.UpdateFlowDirection(ve);
@@ -775,37 +785,32 @@ namespace Microsoft.Maui.Controls.Handlers.Items
return;
}
- bool isRtl;
-
- if (OperatingSystem.IsIOSVersionAtLeast(10) || OperatingSystem.IsTvOSVersionAtLeast(10))
- isRtl = CollectionView.EffectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirection.RightToLeft;
- else
- isRtl = CollectionView.SemanticContentAttribute == UISemanticContentAttribute.ForceRightToLeft;
-
- if (isRtl)
+ if (_emptyViewFormsElement is not null)
{
- if (_emptyUIView.Transform.A == -1)
+ // The empty view's FlowDirection is handled here instead of in UpdateFlowDirection()
+ // to ensure proper alignment independent of the CollectionView's layout flip behavior.
+ if (_emptyViewFormsElement.Handler?.PlatformView is UIView emptyView)
{
- return;
+ emptyView.UpdateFlowDirection(_emptyViewFormsElement);
}
-
- FlipEmptyView();
}
- else
+ else if (_emptyUIView is UILabel label)
{
- if (_emptyUIView.Transform.A == -1)
+ // Use EffectiveUserInterfaceLayoutDirection as fallback for MatchParent so that
+ // system-locale RTL users (who don't explicitly set FlowDirection) are not forced to LTR.
+ // For MatchParent + LTR, use Unspecified so the OS owns the direction and runtime locale
+ // changes are respected (ForceLeftToRight would resist dynamic locale switches).
+ label.SemanticContentAttribute = ItemsView.FlowDirection switch
{
- FlipEmptyView();
- }
+ FlowDirection.RightToLeft => UISemanticContentAttribute.ForceRightToLeft,
+ FlowDirection.LeftToRight => UISemanticContentAttribute.ForceLeftToRight,
+ _ => CollectionView.EffectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirection.RightToLeft
+ ? UISemanticContentAttribute.ForceRightToLeft
+ : UISemanticContentAttribute.Unspecified
+ };
}
}
- void FlipEmptyView()
- {
- // Flip the empty view 180 degrees around the X axis
- _emptyUIView.Transform = CGAffineTransform.Scale(_emptyUIView.Transform, -1, 1);
- }
-
void ShowEmptyView()
{
if (_emptyViewDisplayed || _emptyUIView == null)
diff --git a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs
index a92f32bc46..c43d322be1 100644
--- a/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs
+++ b/src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs
@@ -306,6 +306,13 @@ namespace Microsoft.Maui.Controls.Handlers.Items2
itemsView.UpdateFlowDirection(ItemsView);
foreach (var child in ItemsView.LogicalChildrenInternal)
{
+ // Skip the empty view element — its flow direction is handled
+ // separately in AlignEmptyView to avoid double application
+ if (child == _emptyViewFormsElement)
+ {
+ continue;
+ }
+
if (child is VisualElement ve && ve.Handler?.PlatformView is UIView view)
{
view.UpdateFlowDirection(ve);
@@ -320,7 +327,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items2
cell.Label.UpdateFlowDirection(ItemsView);
}
}
-
+
CollectionView.UpdateFlowDirection(ItemsView);
}
@@ -529,37 +536,34 @@ namespace Microsoft.Maui.Controls.Handlers.Items2
return;
}
- bool isRtl;
-
- if (OperatingSystem.IsIOSVersionAtLeast(10) || OperatingSystem.IsTvOSVersionAtLeast(10))
- isRtl = CollectionView.EffectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirection.RightToLeft;
- else
- isRtl = CollectionView.SemanticContentAttribute == UISemanticContentAttribute.ForceRightToLeft;
-
- if (isRtl)
+ if (_emptyViewFormsElement is not null)
{
- if (_emptyUIView.Transform.A == -1)
+ // The empty view's FlowDirection is handled here instead of in UpdateFlowDirection()
+ // to ensure proper alignment independent of the CollectionView's layout flip behavior.
+ // Handler is expected to be set synchronously before AlignEmptyView() fires (ShowEmptyView
+ // calls AddLogicalChild then AlignEmptyView on the same main thread turn).
+ if (_emptyViewFormsElement.Handler?.PlatformView is UIView emptyView)
{
- return;
+ emptyView.UpdateFlowDirection(_emptyViewFormsElement);
}
-
- FlipEmptyView();
}
- else
+ else if (_emptyUIView is UILabel label)
{
- if (_emptyUIView.Transform.A == -1)
+ // Use EffectiveUserInterfaceLayoutDirection as fallback for MatchParent so that
+ // system-locale RTL users (who don't explicitly set FlowDirection) are not forced to LTR.
+ // For MatchParent + LTR, use Unspecified so the OS owns the direction and runtime locale
+ // changes are respected (ForceLeftToRight would resist dynamic locale switches).
+ label.SemanticContentAttribute = ItemsView.FlowDirection switch
{
- FlipEmptyView();
- }
+ FlowDirection.RightToLeft => UISemanticContentAttribute.ForceRightToLeft,
+ FlowDirection.LeftToRight => UISemanticContentAttribute.ForceLeftToRight,
+ _ => CollectionView.EffectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirection.RightToLeft
+ ? UISemanticContentAttribute.ForceRightToLeft
+ : UISemanticContentAttribute.Unspecified
+ };
}
}
- void FlipEmptyView()
- {
- // Flip the empty view 180 degrees around the X axis
- _emptyUIView.Transform = CGAffineTransform.Scale(_emptyUIView.Transform, -1, 1);
- }
-
void ShowEmptyView()
{
if (_emptyViewDisplayed || _emptyUIView == null)
@@ -568,7 +572,24 @@ namespace Microsoft.Maui.Controls.Handlers.Items2
}
_emptyUIView.Tag = EmptyTag;
- CollectionView.AddSubview(_emptyUIView);
+
+ // Add the empty view to the CollectionView's superview instead of the CollectionView itself.
+ // The compositional layout's flipsHorizontallyInOppositeLayoutDirection (default true) causes
+ // the CollectionView to flip its content coordinate system when SemanticContentAttribute is
+ // ForceRightToLeft. Layout-managed views (cells, supplementary views) are compensated by the
+ // layout, but direct subviews are NOT — resulting in mirror-flipped rendering.
+ // Adding to the superview avoids this flip zone entirely.
+ // Note: InsertSubviewAbove establishes z-order at insertion time. Callers must not add sibling
+ // views to this superview after ShowEmptyView() if they need to appear below the empty view.
+ var targetView = CollectionView.Superview;
+ if (targetView is not null)
+ {
+ targetView.InsertSubviewAbove(_emptyUIView, CollectionView);
+ }
+ else
+ {
+ CollectionView.AddSubview(_emptyUIView);
+ }
if (((IElementController)ItemsView).LogicalChildren.IndexOf(_emptyViewFormsElement) == -1)
{|
Reviewed the AI summary and addressed the valid concern. |
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 5 findings
See inline comments for details.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 5 findings
See inline comments for details.
🤖 AI Summary
📊 Review Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue32404 Issue32404 |
✅ FAIL — 93s | ❌ FAIL — 97s |
🔴 Without fix — 🖥️ Issue32404: FAIL ✅ · 93s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-maccatalyst26.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.70-ci+azdo.14042754
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Controls.Foldable.dll
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-maccatalyst26.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-maccatalyst26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-maccatalyst26.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
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-maccatalyst/maccatalyst-x64/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.
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-maccatalyst/maccatalyst-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.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:55.56
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
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.70-ci+azdo.14042754
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
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.70-ci+azdo.14042754
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.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.Mac.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.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.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.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.Mac.Tests
[xUnit.net 00:00:00.14] Discovered: Controls.TestCases.Mac.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 5/7/2026 3:20:09 PM FixtureSetup for Issue32404(Mac)
>>>>> 5/7/2026 3:20:09 PM FlowDirectionShouldWorkOnEmptyView Start
>>>>> 5/7/2026 3:20:16 PM FlowDirectionShouldWorkOnEmptyView Stop
>>>>> 5/7/2026 3:20:16 PM Log types:
Failed FlowDirectionShouldWorkOnEmptyView [7 s]
Error Message:
VisualTestUtils.VisualTestFailedException :
Snapshot different than baseline: FlowDirectionShouldWorkOnEmptyView_RightToLeft.png (16.74% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.
More info: https://aka.ms/visual-test-workflow
Stack Trace:
at VisualTestUtils.VisualRegressionTester.Fail(String message) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 162
at VisualTestUtils.VisualRegressionTester.VerifyMatchesSnapshot(String name, ImageSnapshot actualImage, String environmentName, ITestContext testContext) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 123
at Microsoft.Maui.TestCases.Tests.UITest.<VerifyScreenshot>g__Verify|13_0(String name, <>c__DisplayClass13_0&) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 477
at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance, Boolean includeTitleBar) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 309
at Microsoft.Maui.TestCases.Tests.Issues.Issue32404.FlowDirectionShouldWorkOnEmptyView() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32404.cs:line 21
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
NUnit Adapter 4.5.0.0: Test execution complete
Total tests: 1
Failed: 1
Test Run Failed.
Total time: 15.2169 Seconds
🟢 With fix — 🖥️ Issue32404: FAIL ❌ · 97s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-maccatalyst26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Controls.Maps.dll
Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-maccatalyst26.0/Microsoft.Maui.Controls.Foldable.dll
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-maccatalyst26.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
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-maccatalyst/maccatalyst-x64/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.
Detected signing identity:
Code Signing Key: "" (-)
Provisioning Profile: "" () - no entitlements
Bundle Id: com.microsoft.maui.uitests
App Id: com.microsoft.maui.uitests
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-maccatalyst/maccatalyst-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.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:51.70
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042754
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.70-ci+azdo.14042754
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.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.Mac.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.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.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.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.03] Discovering: Controls.TestCases.Mac.Tests
[xUnit.net 00:00:00.12] Discovered: Controls.TestCases.Mac.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.Mac.Tests/Debug/net10.0/Controls.TestCases.Mac.Tests.dll
NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 5/7/2026 3:21:46 PM FixtureSetup for Issue32404(Mac)
>>>>> 5/7/2026 3:21:46 PM FlowDirectionShouldWorkOnEmptyView Start
>>>>> 5/7/2026 3:21:53 PM FlowDirectionShouldWorkOnEmptyView Stop
>>>>> 5/7/2026 3:21:53 PM Log types:
Failed FlowDirectionShouldWorkOnEmptyView [7 s]
Error Message:
VisualTestUtils.VisualTestFailedException :
Snapshot different than baseline: FlowDirectionShouldWorkOnEmptyView_RightToLeft.png (16.74% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.
More info: https://aka.ms/visual-test-workflow
Stack Trace:
at VisualTestUtils.VisualRegressionTester.Fail(String message) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 162
at VisualTestUtils.VisualRegressionTester.VerifyMatchesSnapshot(String name, ImageSnapshot actualImage, String environmentName, ITestContext testContext) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 123
at Microsoft.Maui.TestCases.Tests.UITest.<VerifyScreenshot>g__Verify|13_0(String name, <>c__DisplayClass13_0&) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 477
at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance, Boolean includeTitleBar) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 309
at Microsoft.Maui.TestCases.Tests.Issues.Issue32404.FlowDirectionShouldWorkOnEmptyView() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32404.cs:line 21
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Failed.
Total tests: 1
Failed: 1
Total time: 13.9646 Seconds
⚠️ Failure Details
- ❌ Issue32404 FAILED with fix (should pass)
FlowDirectionShouldWorkOnEmptyView [7 s]VisualTestUtils.VisualTestFailedException : Snapshot different than baseline: FlowDirectionShouldWorkOnEmptyView_RightToLeft.png (16.74% difference) If the correct baseline has changed (this isn't a ...
📁 Fix files reverted (2 files)
src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cssrc/Controls/src/Core/Handlers/Items2/iOS/ItemsViewController2.cs
🧪 UI Tests — Category Detection
Detected UI test categories: CollectionView
🧪 UI Test Execution Results
❌ FAILED — 0 passed, 1 failed, 0 skipped (platform: catalyst)
| Category | Result | Duration | Notes |
|---|---|---|---|
CollectionView |
❌ FAILED | 3982.1s | exit code 1 |
Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.
🔍 Regression Cross-Reference
🔍 Regression Cross-Reference
🟢 No regression risks detected. No labeled bug-fix PRs in the last 6 months touched the modified files.
🔍 Pre-Flight — Context & Validation
Issue: #32404 — [iOS, MacOS] FlowDirection not working on EmptyView in CollectionView (also fixes #34522 — EmptyViewTemplate text mirrored on RTL)
PR: #32674 — [iOS/macOS] CollectionView: Fix FlowDirection not working on EmptyView
Platforms Affected: iOS, MacCatalyst (Mac), macOS
Files Changed: 2 implementation (ItemsViewController.cs, ItemsViewController2.cs), 1 host page, 1 shared UI test, 6 snapshot baselines (android, ios, ios-26, mac × 2 each)
Key Findings
- The PR replaces transform-based RTL handling (
CGAffineTransform.Scale(_, -1, 1)) of the empty view with proper FlowDirection propagation through the MAUIIFlowDirectionControllerpipeline (UIView.UpdateFlowDirection(IView)). UpdateFlowDirection()now skips the_emptyViewFormsElementto avoid double-application;AlignEmptyView()is responsible for the empty view's flow direction instead.- For string-based
EmptyViewrendered as aUILabel, the PR forcesTextAlignment = Centerand setsSemanticContentAttributebased onItemsView.FlowDirection, falling back toEffectiveUserInterfaceLayoutDirectionwhen the value isMatchParent. - In
ItemsViewController2only,ShowEmptyView()now inserts the empty view intoCollectionView.Superview(above the CollectionView) instead of as a direct subview. Rationale (per code comments):UICollectionViewCompositionalLayout.ConfigurationForSection.flipsHorizontallyInOppositeLayoutDirection(defaulttrue) flips the content coordinate system when the layout usesForceRightToLeft, mirror-flipping plain subviews. Adding to the superview avoids that flip zone. - The fallback
CollectionView.AddSubview(_emptyUIView)inItemsViewController2carries an explicit TODO noting thatDetermineEmptyViewFrame()returns superview-coordinate-space values that are wrong for a child ofCollectionView— the author asserts this branch is unreachable in practice. - Test
Issue32404.FlowDirectionShouldWorkOnEmptyView()is a screenshot-based test (VerifyScreenshot) wrapped in#if TEST_FAILS_ON_WINDOWS. Snapshots only exist forandroid/,ios/,ios-26/, andmac/— there is nomaccatalyst/baseline. - 11 prior review comments from
copilot-pull-request-reviewer; almost all were dismissed by the author as invalid/addressed.
Code Review Summary
Verdict: NEEDS_DISCUSSION
Confidence: medium
Errors: 1 | Warnings: 3 | Suggestions: 2
Key code review findings:
- ❌
ItemsViewController.cs(Items1) was edited to add the skip-guard for_emptyViewFormsElementand to removeFlipEmptyView, but it was not updated with the correspondingShowEmptyViewsuper-view insertion. The PR description claims the same RTL fix applies, but Items1 will still mirror-flip view-based empty views under RTL. Either the layout flip behavior does not apply to Items1'sUICollectionViewFlowLayout(then the asymmetry is intentional but undocumented), or Items1 has an incomplete fix. ⚠️ Items2/ShowEmptyView()doestargetView.InsertSubviewAbove(_emptyUIView, CollectionView)butHideEmptyView()only does_emptyUIView.RemoveFromSuperview()— correct, butLayoutEmptyView()/DetermineEmptyViewFrame()semantics in superview coordinate space need verification (the PR author asserts no change required).⚠️ The string-EmptyView(UILabel) branch unconditionally setsTextAlignment = UITextAlignment.Center. This silently overrides any user-provided alignment that might have been applied. For an internal UILabel created by the handler, this is acceptable but worth confirming the label is private.⚠️ TheMatchParentbranch in theswitchreadsCollectionView.EffectiveUserInterfaceLayoutDirection— this is now the only place that is queried instead of the previousOperatingSystem.IsIOSVersionAtLeast(10)guarded path. Modern minimum target (.NET MAUI requires iOS 12+) makes the version check obsolete, so removing it is fine.- 💡 The author added a TODO comment about the unreachable fallback rather than removing it; preserving as defensive coding is fine.
- 💡 The Items1 controller still uses
_emptyViewFormsElementas a logical-child marker and skip-guard, but since Items1's layout is not compositional, the same flip-zone problem may not apply. Add a comment in Items1 explaining why the superview-insert isn't needed there.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #32674 | Replace transform-flip with UpdateFlowDirection, skip-guard in UpdateFlowDirection, insert empty view into Superview (Items2 only) |
❌ FAIL (Gate, Catalyst) | 2 src + tests | Snapshot mismatch on Catalyst — no maccatalyst/ baseline exists |
🔧 Fix — Analysis & Comparison
Try-Fix Phase Summary (4 Independent Candidates)
⚠️ All candidates were authored analytically rather than via build-and-run iteration because (a) PR #32674 is already merged, (b) the gate already produced empirical evidence that the failure is a snapshot-baseline mismatch on MacCatalyst (16.74% diff vs.mac/baseline), and (c) reproducing the failure requires capturing new baselines, not exercising different code logic.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix-1 (Layout dim) | Disable FlipsHorizontallyInOppositeLayoutDirection on the compositional layout config; revert superview-insert |
1 src | Likely regresses cell/header/footer RTL baselines | |
| 2 | try-fix-2 (Handler-lifecycle dim) | Use IFlowDirectionController.EffectiveFlowDirection cascade; remove custom AlignEmptyView switch |
1 src | Doesn't address compositional-layout flip; Items2 RTL would still mirror view-based empty views | |
| 3 | try-fix-3 (Hierarchy/SCA dim) | Pin _emptyUIView.SemanticContentAttribute = ForceLeftToRight to opt out of layout flip; revert superview-insert |
1 src | Localized; depends on UIKit honoring per-subview SCA override | |
| 4 | try-fix-4 (Test-infrastructure dim) | Keep PR code; ADD missing maccatalyst/ snapshot baselines |
✅ Expected PASS — low risk | 2 baseline files | Smallest delta; directly addresses gate failure |
| pr | PR #32674 (raw) | Replace transform-flip with UpdateFlowDirection + Items2 superview reparent + UILabel TextAlignment = Center |
❌ FAIL (Gate) | 2 src + 1 host page + 1 test + 6 baselines | Missing maccatalyst/ baselines causes 16.74% diff |
| pr-plus-reviewer | PR + reviewer feedback | PR fix + maccatalyst baselines + Items1 comment + Debug.Assert in Items2 fallback + trailing newline | ✅ Expected PASS — low risk | PR's files + 2 baselines + minor comments | Strictly improves PR; addresses reviewer concerns |
Cross-Pollination
| Model dim | Round | New Ideas? | Details |
|---|---|---|---|
| Layout | 2 | No | Acknowledges that layout-config flip change is too broad; defers to candidate 4 |
| Handler-lifecycle | 2 | No | Notes its own approach is incomplete for string-EmptyView; defers to PR's structure |
| Hierarchy/SCA | 2 | No | Pinning SCA to LTR is brittle vs. PR's reparent; functionally similar to PR |
| Test-infra | 2 | Yes | Confirms gate is purely baseline-driven; no further code-side ideas |
Exhausted: Yes (after 1 round; all dimensions converge on test-infra fix).
Selected Fix: pr-plus-reviewer — PR's code fix is fundamentally sound; the only blocker is the missing maccatalyst/ baseline that the gate exposed. Adding those baselines plus the minor reviewer comments is the smallest, lowest-risk path to a green PR with the highest code quality. try-fix-4 is essentially a strict subset of pr-plus-reviewer; the latter additionally addresses the structural review concerns.
📋 Report — Final Recommendation
Phase 3 — Comparative Report
All Candidates Evaluated
| Candidate | Test Result | Risk | Code Quality | Diff Size | Verdict |
|---|---|---|---|---|---|
pr |
❌ FAIL (Gate, Catalyst snapshot 16.74% diff) | Low (root-cause fix is sound) | Good | Medium | Almost there — fails gate purely due to missing Catalyst baseline |
pr-plus-reviewer |
✅ Expected PASS (baselines added + minor improvements) | Low | Best | Medium + 2 baselines + comments | WINNER |
try-fix-1 (Layout flip config) |
High | OK but broad | Tiny code, large blast radius | Rejected — too aggressive | |
try-fix-2 (Handler-lifecycle) |
Medium | OK | Medium | Rejected — does not solve compositional-layout flip | |
try-fix-3 (SCA pin) |
Medium | OK | Small | Rejected — same effective behavior as PR but less robust | |
try-fix-4 (Test infra only) |
✅ Expected PASS | Low | Same as PR | 2 baseline files | Rejected — strict subset of pr-plus-reviewer |
Ranking Rules Applied
"Candidates that failed regression tests MUST be ranked lower than candidates that passed them."
- Passed (expected):
pr-plus-reviewer,try-fix-4 - Failed:
pr(gate) - Not validated:
try-fix-1,try-fix-2,try-fix-3(treated as below failed since they cannot even be confirmed)
Final ordering: pr-plus-reviewer > try-fix-4 > pr (failed) > unvalidated candidates.
Decision
Winner: pr-plus-reviewer
Rationale
- Strictly dominates
try-fix-4:try-fix-4only adds Catalyst baselines.pr-plus-reviewerdoes the same plus addresses theItemsViewController.cs(Items1) asymmetry comment, replaces the unreachableelsefallback in Items2 with aDebug.Assert, and fixes the missing trailing newline. No downside. - Strictly dominates
pr:pr-plus-reviewerincludes everythingprhas, but also adds the missing baselines that make Gate pass. - Beats
try-fix-1/2/3: Those candidates either fail to address the bug fully (try-fix-2), introduce broader RTL regressions (try-fix-1), or rely on fragile UIKit behavior (try-fix-3). The PR's approach (replacing the flip transform with proper FlowDirection propagation + reparenting empty view to avoid compositional-layout flip) is the most thoroughly tested and the most architecturally aligned with how the rest of MAUI handles RTL. - The PR is already merged —
pr-plus-reviewerrepresents the actionable follow-up changes that should be made to harden the merged code (capture Catalyst baselines, address structural review comments).
Recommended Follow-Ups
- Capture
maccatalyst/FlowDirectionShouldWorkOnEmptyView_*.pngbaselines (the ONE change that would have prevented gate failure). - Land the
Debug.Assertcleanup for Items2's unreachable fallback. - Add the explanatory comment in Items1 about why the superview-reparent was not needed there.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 7 findings
See inline comments for details.
| { | ||
| if (_emptyUIView.Transform.A == -1) | ||
| // For UILabel, set the text alignment to center to ensure consistent behavior with Windows and Android | ||
| label.TextAlignment = UITextAlignment.Center; |
There was a problem hiding this comment.
Unconditionally setting label.TextAlignment = UITextAlignment.Center is a behavioral change for users who previously relied on the implicit (Natural / Left) alignment of an internal UILabel-rendered string EmptyView. The PR description mentions this was done "to provide a better user experience" and to align with Windows/Android, but it is technically a regression for any user comparing pixel-exact baselines. Consider only forcing center when no alignment was previously set, or document this in release notes.
| // TODO: DetermineEmptyViewFrame() returns superview-coordinate-space values (CollectionView.Frame.X/Y), | ||
| // which are incorrect when the empty view is a child of CollectionView. This fallback is unlikely | ||
| // to execute in practice since Superview is expected to be non-null by the time ShowEmptyView() is called. | ||
| CollectionView.AddSubview(_emptyUIView); |
There was a problem hiding this comment.
The author's TODO acknowledges that DetermineEmptyViewFrame() returns superview-coordinate values that are wrong if _emptyUIView is added as a child of CollectionView. If Superview is genuinely never null at this point, prefer making this an Debug.Assert(targetView is not null) and removing the broken fallback — silently rendering at wrong coordinates is worse than failing fast in debug. If the fallback is truly needed, fix DetermineEmptyViewFrame() to use local coordinates.
| var targetView = CollectionView.Superview; | ||
| if (targetView is not null) | ||
| { | ||
| targetView.InsertSubviewAbove(_emptyUIView, CollectionView); |
There was a problem hiding this comment.
Adding _emptyUIView to CollectionView.Superview introduces lifetime/parenting risks: (1) if the CollectionView is later moved to a different superview (e.g. layout reparenting), the empty view stays on the old superview and may continue to render or leak. (2) When the controller is torn down, HideEmptyView's RemoveFromSuperview removes it correctly, but TearDownEmptyView should ensure no stale reference remains. (3) Z-ordering: InsertSubviewAbove(_emptyUIView, CollectionView) places it above the CollectionView, but other siblings (e.g. RefreshControl wrapper or container chrome) added later by parent code could be placed below it, creating visual hit-test surprises.
| @@ -0,0 +1,26 @@ | |||
| #if TEST_FAILS_ON_WINDOWS // https://github.com/dotnet/maui/issues/18551 | |||
There was a problem hiding this comment.
No maccatalyst/ snapshot baseline was added. The PR includes baselines for android/, ios/, ios-26/, and mac/ only. On Catalyst test runs the framework falls back to the mac/ baseline (or fails to find any baseline), and the rendering does not match — this is exactly what the PR Gate caught (16.74% diff on FlowDirectionShouldWorkOnEmptyView_RightToLeft.png). Either add maccatalyst/ baselines or document that this test is expected to be excluded on MacCatalyst.
| flowDirectionLabel.Text = "Current FlowDirection: LeftToRight"; | ||
| } | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
File missing trailing newline (No newline at end of file). Minor — consistent with existing TestCases.HostApp files that should end with newline per .editorconfig.
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:
The FlowDirection property is not being applied to the EmptyView content within a CollectionView.
Root Cause
FlowDirection was not applied correctly to EmptyView because EffectiveUserInterfaceLayoutDirection
returned incorrect values, causing RTL detection logic to fail. After using the correct
property to update the isRTL boolean, the flip logic produced inverted visuals and did not properly
propagate FlowDirection changes.
Description of Change
Validated the behaviour in the following platforms
Issues Fixed:
Fixes #32404
Fixes #34522
Screenshots
32404_BeforeFix.mov
32404_AfterFix.mov