diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986.cs index 262d38aa3a62..d2e0de68ed79 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28986.cs @@ -12,7 +12,40 @@ public class Issue28986 : _IssuesUITest public Issue28986(TestDevice device) : base(device) { } + + [Test] + [Category(UITestCategories.SafeAreaEdges)] + public void SoftInputDoesNotApplyBottomPaddingWhenKeyboardHidden() + { + // This test validates the fix for issue #31870 + // When SafeAreaEdges.Bottom is set to SoftInput and the keyboard is NOT showing, + // there should be NO bottom padding from the navigation bar. + App.WaitForElement("ContentGrid"); + + // First, set to None to get the baseline position (no safe area padding) + App.Tap("GridResetNoneButton"); + var noneRect = App.WaitForElement("MainGrid").GetRect(); + // Now set bottom edge to SoftInput (keyboard is still hidden) + App.Tap("GridSetBottomSoftInputButton"); + + // Wait for layout to update + App.WaitForElement("MainGrid"); + + // Get the current settings to verify SoftInput is set + var currentSettings = App.FindElement("CurrentSettings").GetText(); + Assert.That(currentSettings, Does.Contain("Bottom:SoftInput"), + "Bottom edge should be set to SoftInput"); + + // Get the rect after setting SoftInput + var softInputRect = App.WaitForElement("MainGrid").GetRect(); + + // Verify that the bottom position is the same as None (no padding applied) + // The height should be the same because SoftInput should not add padding when keyboard is hidden + Assert.That(softInputRect.Height, Is.EqualTo(noneRect.Height).Within(5), + "MainGrid height should be the same with SoftInput as with None when keyboard is hidden (no bottom padding)"); + } + [Test] [Category(UITestCategories.SafeAreaEdges)] public void SafeAreaMainGridBasicFunctionality() diff --git a/src/Core/src/Platform/Android/SafeAreaExtensions.cs b/src/Core/src/Platform/Android/SafeAreaExtensions.cs index 06a5b982d9aa..a18734dba83a 100644 --- a/src/Core/src/Platform/Android/SafeAreaExtensions.cs +++ b/src/Core/src/Platform/Android/SafeAreaExtensions.cs @@ -235,14 +235,20 @@ internal static double GetSafeAreaForEdge(SafeAreaRegions safeAreaRegion, double } // Handle SoftInput specifically - only apply keyboard insets for bottom edge when keyboard is showing - if (isKeyboardShowing && edge == 3) + if (edge == 3) { - if (SafeAreaEdges.IsSoftInput(safeAreaRegion)) - return keyBoardInsets.Bottom; - - // if they keyboard is showing then we will just return 0 for the bottom inset - // because that part of the view is covered by the keyboard so we don't want to pad the view - return 0; + if (SafeAreaEdges.IsSoftInput(safeAreaRegion)) + { + // SoftInput only applies padding when keyboard is showing + return isKeyboardShowing ? keyBoardInsets.Bottom : 0; + } + + if (isKeyboardShowing) + { + // if the keyboard is showing then we will just return 0 for the bottom inset + // because that part of the view is covered by the keyboard so we don't want to pad the view + return 0; + } } // All other regions respect safe area in some form diff --git a/src/Core/src/Platform/iOS/MauiView.cs b/src/Core/src/Platform/iOS/MauiView.cs index dc04aa9a545d..e8cf7d5ce28a 100644 --- a/src/Core/src/Platform/iOS/MauiView.cs +++ b/src/Core/src/Platform/iOS/MauiView.cs @@ -143,16 +143,25 @@ SafeAreaRegions GetSafeAreaRegionForEdge(int edge) return SafeAreaRegions.None; } - static double GetSafeAreaForEdge(SafeAreaRegions safeAreaRegion, double originalSafeArea) + double GetSafeAreaForEdge(SafeAreaRegions safeAreaRegion, double originalSafeArea, int edge) { // Edge-to-edge content - no safe area padding if (safeAreaRegion == SafeAreaRegions.None) return 0; + // Handle SoftInput specifically - only apply padding when keyboard is actually showing + if (edge == 3 && SafeAreaEdges.IsSoftInput(safeAreaRegion)) + { + // SoftInput only applies padding when keyboard is showing + // When keyboard is hidden, return 0 to avoid showing home indicator padding + if (!_isKeyboardShowing) + return 0; + } + // All other regions respect safe area in some form // This includes: // - Default: Platform default behavior - // - All: Obey all safe area insets + // - All: Obey all safe area insets (includes SoftInput when keyboard) // - SoftInput: Always pad for keyboard/soft input // - Container: Content flows under keyboard but stays out of bars/notch // - Any combination of the above flags @@ -336,10 +345,10 @@ SafeAreaPadding GetAdjustedSafeAreaInsets() if (View is ISafeAreaView2) { // Apply safe area selectively per edge based on SafeAreaRegions - var left = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(0), baseSafeArea.Left); - var top = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(1), baseSafeArea.Top); - var right = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(2), baseSafeArea.Right); - var bottom = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(3), baseSafeArea.Bottom); + var left = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(0), baseSafeArea.Left, 0); + var top = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(1), baseSafeArea.Top, 1); + var right = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(2), baseSafeArea.Right, 2); + var bottom = GetSafeAreaForEdge(GetSafeAreaRegionForEdge(3), baseSafeArea.Bottom, 3); return new SafeAreaPadding(left, right, top, bottom); }