From d2bc039f933714324a841d9e97fc54ecc5d0a328 Mon Sep 17 00:00:00 2001 From: Jakub Florkowski Date: Thu, 7 Aug 2025 01:35:31 +0200 Subject: [PATCH 1/5] Fix: Ensure AppShell.OnSizeAllocated is called on Android and iOS in .NET 10 --- .../Handlers/Shell/Android/ShellFlyoutRenderer.cs | 8 ++++++++ .../Compatibility/Handlers/Shell/iOS/ShellRenderer.cs | 2 ++ .../Core/PublicAPI/net-android/PublicAPI.Unshipped.txt | 1 + 3 files changed, 11 insertions(+) diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs index c243bacdc684..9da145a43c75 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs @@ -407,6 +407,14 @@ void UpdateScrim(Brush backdrop) } } + protected override void OnLayout(bool changed, int left, int top, int right, int bottom) + { + base.OnLayout(changed, left, top, right, bottom); + + var destination = Context.ToCrossPlatformRectInReferenceFrame(left, top, right, bottom); + Shell.Frame = destination; + } + internal void Disconnect() { ShellController?.RemoveAppearanceObserver(this); diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs index 4568795b1fef..2dd01ebaea36 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs @@ -141,6 +141,8 @@ public override void ViewDidLayoutSubviews() base.ViewDidLayoutSubviews(); if (_currentShellItemRenderer != null) _currentShellItemRenderer.ViewController.View.Frame = View.Bounds; + + Shell.Frame = View.Bounds.ToRectangle(); } public override void ViewDidLoad() diff --git a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt index cc66326af4d7..b494b4067850 100644 --- a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -1,4 +1,5 @@ #nullable enable +override Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.OnLayout(bool changed, int left, int top, int right, int bottom) -> void override Microsoft.Maui.Controls.Shapes.Shape.OnPropertyChanged(string? propertyName = null) -> void ~override Microsoft.Maui.Controls.Handlers.Items.MauiRecyclerView.OnInterceptTouchEvent(Android.Views.MotionEvent e) -> bool ~override Microsoft.Maui.Controls.Handlers.Items.MauiRecyclerView.OnTouchEvent(Android.Views.MotionEvent e) -> bool From 1d50303b9991a12660b097c9cc13f7be33053c55 Mon Sep 17 00:00:00 2001 From: Jakub Florkowski Date: Sat, 9 Aug 2025 12:10:58 +0200 Subject: [PATCH 2/5] Add test for MeasureInvalidated on Shell frame set Introduces a unit test to verify that setting the Shell's Frame property triggers the MeasureInvalidated event exactly once. This ensures correct layout invalidation behavior when the frame changes. --- .../DeviceTests/Elements/Shell/ShellTests.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs index 9b2c887e8a1f..e19a1e193880 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs @@ -20,6 +20,8 @@ #if ANDROID || IOS || MACCATALYST using ShellHandler = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer; +using Microsoft.Maui.Graphics; + #endif #if IOS || MACCATALYST @@ -1139,6 +1141,32 @@ await CreateHandlerAndAddToWindow(shell, _ => }); } + [Fact] + public async Task SettingFrameDoesTriggerInvalidatedMeasure() + { + SetupBuilder(); + + int measureInvalidatedCount = 0; + + var page = new ContentPage(); + var shell = await CreateShellAsync(shell => + { + shell.CurrentItem = new ShellContent { Content = page }; + }); + + shell.MeasureInvalidated += (s, e) => + { + measureInvalidatedCount++; + }; + + shell.Frame = new Rect(0, 0, 100, 100); + + await CreateHandlerAndAddToWindow(shell, _ => + { + Assert.Equal(1, measureInvalidatedCount); + }); + } + protected Task CreateShellAsync(Action action) => InvokeOnMainThreadAsync(() => { From 539c6facdb9ccb9f3eb866dac37f9503e0be54bb Mon Sep 17 00:00:00 2001 From: Jakub Florkowski Date: Sun, 31 Aug 2025 12:53:42 +0200 Subject: [PATCH 3/5] Update ShellTests.cs --- src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs index e19a1e193880..de48071152fe 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs @@ -12,15 +12,14 @@ using Microsoft.Maui.Controls.Handlers.Items; using Microsoft.Maui.Devices; using Microsoft.Maui.DeviceTests.Stubs; +using Microsoft.Maui.Graphics; using Microsoft.Maui.Handlers; using Microsoft.Maui.Hosting; using Microsoft.Maui.Platform; using Xunit; using static Microsoft.Maui.DeviceTests.AssertHelpers; - #if ANDROID || IOS || MACCATALYST using ShellHandler = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer; -using Microsoft.Maui.Graphics; #endif From befa08198057f65752c9eae35feae2a92308be92 Mon Sep 17 00:00:00 2001 From: Jakub Florkowski Date: Tue, 16 Sep 2025 13:36:43 +0200 Subject: [PATCH 4/5] Update ShellFlyoutRenderer.cs --- .../Handlers/Shell/Android/ShellFlyoutRenderer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs index 9da145a43c75..c3fbad7bd18c 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs @@ -412,7 +412,8 @@ protected override void OnLayout(bool changed, int left, int top, int right, int base.OnLayout(changed, left, top, right, bottom); var destination = Context.ToCrossPlatformRectInReferenceFrame(left, top, right, bottom); - Shell.Frame = destination; + if (Shell.Frame != destination) + Shell.Frame = destination; } internal void Disconnect() From e9e6211a132f2cc90898f5eab58bc95b5479461e Mon Sep 17 00:00:00 2001 From: Jakub Florkowski Date: Thu, 2 Apr 2026 12:11:46 +0200 Subject: [PATCH 5/5] Address review: fix Windows Rect ambiguity, add iOS frame guard - Use fully qualified Microsoft.Maui.Graphics.Rect in ShellTests to fix Windows compilation error (CS0246) - Add 'if (Shell.Frame != destination)' guard in iOS ShellRenderer to avoid unnecessary frame updates during layout passes - Remove unused 'using Microsoft.Maui.Graphics' import - Restore original whitespace formatting in using directives Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs | 4 +++- src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs index 2dd01ebaea36..aeb289655c95 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellRenderer.cs @@ -142,7 +142,9 @@ public override void ViewDidLayoutSubviews() if (_currentShellItemRenderer != null) _currentShellItemRenderer.ViewController.View.Frame = View.Bounds; - Shell.Frame = View.Bounds.ToRectangle(); + var destination = View.Bounds.ToRectangle(); + if (Shell.Frame != destination) + Shell.Frame = destination; } public override void ViewDidLoad() diff --git a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs index de48071152fe..eff3c01e31a1 100644 --- a/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/Shell/ShellTests.cs @@ -12,15 +12,14 @@ using Microsoft.Maui.Controls.Handlers.Items; using Microsoft.Maui.Devices; using Microsoft.Maui.DeviceTests.Stubs; -using Microsoft.Maui.Graphics; using Microsoft.Maui.Handlers; using Microsoft.Maui.Hosting; using Microsoft.Maui.Platform; using Xunit; using static Microsoft.Maui.DeviceTests.AssertHelpers; + #if ANDROID || IOS || MACCATALYST using ShellHandler = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer; - #endif #if IOS || MACCATALYST @@ -1158,7 +1157,7 @@ public async Task SettingFrameDoesTriggerInvalidatedMeasure() measureInvalidatedCount++; }; - shell.Frame = new Rect(0, 0, 100, 100); + shell.Frame = new Microsoft.Maui.Graphics.Rect(0, 0, 100, 100); await CreateHandlerAndAddToWindow(shell, _ => {