From 7adc66df1f4d680157cb428ea680bd3e3de898c1 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Mon, 20 Apr 2026 13:57:14 +0000 Subject: [PATCH] Fix safe area calcs for navigation page (#21221) * fix safe area calcs for navigation page * update nav bar effective height on safe area change * reset nav bar height if visibility changes * add tests --- src/Avalonia.Controls/Page/NavigationPage.cs | 19 ++++++++++++++----- .../NavigationPageTests.cs | 13 +++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Controls/Page/NavigationPage.cs b/src/Avalonia.Controls/Page/NavigationPage.cs index 525851af89..8297a157cf 100644 --- a/src/Avalonia.Controls/Page/NavigationPage.cs +++ b/src/Avalonia.Controls/Page/NavigationPage.cs @@ -639,6 +639,9 @@ namespace Avalonia.Controls "Direct assignment to NavigationPage.Pages is not supported. Use PushAsync, PopAsync, InsertPage, RemovePage, or ReplaceAsync to modify the navigation stack."); } + if (change.Property == SafeAreaPaddingProperty) + UpdateEffectiveBarHeight(); + base.OnPropertyChanged(change); } @@ -750,7 +753,10 @@ namespace Avalonia.Controls { if (_contentHost != null && _navBar != null) { - _navBar.Padding = new Thickness(SafeAreaPadding.Left, SafeAreaPadding.Top, SafeAreaPadding.Right, 0); + var safeAreaPadding = IsNavBarEffectivelyVisible ? new Thickness(SafeAreaPadding.Left, 0, SafeAreaPadding.Right, SafeAreaPadding.Bottom) : SafeAreaPadding; + _navBar.Padding = IsNavBarEffectivelyVisible + ? new Thickness(SafeAreaPadding.Left, SafeAreaPadding.Top, SafeAreaPadding.Right, 0) + : default; if (_pagePresenter != null) _pagePresenter.Padding = Padding; @@ -759,8 +765,8 @@ namespace Avalonia.Controls if (CurrentPage != null) { - var remainingSafeArea = Padding.GetRemainingSafeAreaPadding(SafeAreaPadding); - CurrentPage.SafeAreaPadding = new Thickness(remainingSafeArea.Left, 0, remainingSafeArea.Right, remainingSafeArea.Bottom); + var remainingSafeArea = Padding.GetRemainingSafeAreaPadding(safeAreaPadding); + CurrentPage.SafeAreaPadding = new Thickness(remainingSafeArea.Left, remainingSafeArea.Top, remainingSafeArea.Right, remainingSafeArea.Bottom); } foreach (var modal in _modalStack) @@ -2148,8 +2154,11 @@ namespace Avalonia.Controls private void UpdateEffectiveBarHeight() { - EffectiveBarHeight = (CurrentPage != null ? GetBarHeightOverride(CurrentPage) : null) ?? BarHeight; - PseudoClasses.Set(":nav-bar-compact", EffectiveBarHeight < 40); + var contentBarHeight = (CurrentPage != null ? GetBarHeightOverride(CurrentPage) : null) ?? BarHeight; + EffectiveBarHeight = contentBarHeight + SafeAreaPadding.Top; + PseudoClasses.Set(":nav-bar-compact", contentBarHeight < 40); + + UpdateContentSafeAreaPadding(); } private void ApplyNavBarVisibility() diff --git a/tests/Avalonia.Controls.UnitTests/NavigationPageTests.cs b/tests/Avalonia.Controls.UnitTests/NavigationPageTests.cs index 78fe1a69d5..5ac4cf2dfe 100644 --- a/tests/Avalonia.Controls.UnitTests/NavigationPageTests.cs +++ b/tests/Avalonia.Controls.UnitTests/NavigationPageTests.cs @@ -1385,6 +1385,19 @@ public class NavigationPageTests var nav = new NavigationPage { IsGestureEnabled = value }; Assert.Equal(value, nav.IsGestureEnabled); } + + [Fact] + public async Task SafeAreaPadding_Affeccts_Nav_Bar_Height() + { + var nav = new NavigationPage() + { + SafeAreaPadding = new Thickness(10) + }; + var page = new ContentPage(); + NavigationPage.SetBarHeightOverride(page, 60.0); + await nav.PushAsync(page); + Assert.Equal(70.0, nav.EffectiveBarHeight); + } } public class AttachedPropertyTests : ScopedTestBase