maui icon indicating copy to clipboard operation
maui copied to clipboard

Fix keyboard overlap on Android when SoftInput.AdjustResize is set

Open Copilot opened this issue 2 months ago • 44 comments

[!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!

Description of Change

Fixed a regression in .NET 10 RC2 where the keyboard overlaps Entry controls when developers set SoftInput.AdjustResize in MainActivity, breaking the standard Android resize behavior that worked in .NET 9.

Root Cause: WindowCompat.SetDecorFitsSystemWindows(Window, false) in MauiAppCompatActivity disabled automatic window resizing. The inset handler only applied keyboard padding when SafeAreaRegions.SoftInput was explicitly set, ignoring the window's SoftInputMode.

Changes Made:

  1. SafeAreaExtensions.cs - Enhanced to detect window's SoftInputMode and apply keyboard insets when AdjustResize is set, regardless of SafeAreaRegions settings

    • Apply keyboard insets to all container types (drawer layouts, coordinator layouts, etc.) when AdjustResize is set
    • Replaced magic numbers (0, 1, 2, 3) with named constants (EdgeLeft, EdgeTop, EdgeRight, EdgeBottom) for better code readability
    • Refactored duplicated inset consumption logic in ApplyAdjustedSafeAreaInsetsPx
    • Fixed GetSafeAreaForEdge to return 0 for SoftInput-only regions when keyboard is hidden
    • Ensured keyboard-related padding only applies when keyboard is actually visible
  2. UI Tests - Added comprehensive test coverage:

    • Issue32041.xaml/.cs: Tests AdjustResize mode - verifies keyboard insets ARE applied when keyboard shows
    • Issue32041AdjustPan.xaml/.cs: Tests AdjustPan mode - verifies keyboard insets are NOT applied (Android handles panning)
  3. Cross-platform build fixes - Wrapped using Android.Views; with #if ANDROID in 14 test files to fix build errors on iOS, Windows, and MacCatalyst

Key Behavior:

  • When SoftInput.AdjustResize is set: Keyboard insets are applied to push content up, avoiding overlap
  • When SoftInput.AdjustPan is set: No insets applied (Android natively pans the window)
  • When SafeAreaEdges=SoftInput only and keyboard is hidden: Returns 0 padding (no unnecessary safe area insets)

All existing unit tests pass (45/45 SafeArea tests).

Issues Fixed

Fixes #32041

Original prompt

This section details on the original issue you should resolve

<issue_title>net 10 rc2 keyboard overlap android</issue_title> <issue_description>### Description

if you have an entry at the bottom of the screen , the keyboards ovelarps it and you cannot see anything, as you can imagine we have applications where a user is asked to input lots of data and all the entries are overlapped!

Steps to Reproduce

  1. Create a page in maui .net 10 rc2
  2. Place an entry at the bottom of the screen
  3. Start typing.. and the keyboard will overlap the entry
  4. Add below to MainActivity
  5. I have attached both repo - net 9 and 10
protected override void OnCreate(Bundle? savedInstanceState)
       {
           base.OnCreate(savedInstanceState);
           Window?.SetSoftInputMode(SoftInput.AdjustResize | SoftInput.StateUnspecified);

       }
  1. Works in .net 9 but not in .net 10See below net 9 on the left and .net 10 RC2 on the right!

Image

MauiAppNe10Overlap.zip MauiNet9Overlap.zip

Link to public reproduction project repository

No response

Version with bug

10.0.0-rc.2

Is this a regression from previous behavior?

Yes, this used to work in .NET MAUI

Last version that worked well

9.0.111 SR11.1

Affected platforms

Android

Affected platform versions

No response

Did you find any workaround?

none

Relevant log output


```</issue_description>

<agent_instructions>If the user has set the Android Window's SoftInput mode to AdjustResize then we should inset the top level view on the android app if the softinput is open . I'm not sure the best fix here, what we might do is set the inset listener on the container view at the top level and then pad that if the softinput is open and they've set the window to adjust resize, or we add the inset listener to the DecorView. Not sure, need to test out a few scenarios</agent_instructions>

## Comments on the Issue (you are @copilot in this section)

<comments>
<comment_new><author>@jsuarezruiz</author><body>
@NirmalKumarYuvaraj I have seen Shane assigned you to review it. My thoughts:
- I think the regression comes from https://github.com/dotnet/maui/pull/31798/files
- The issue occurs because `WindowCompat.SetDecorFitsSystemWindows(Window, false)` was being called in `MauiAppCompatActivity.OnCreate()`. When set to false, this tells Android that the app will handle all window insets manually, which disables the default `SoftInput.AdjustResize` behavior.</body></comment_new>
<comment_new><author>@PureWeen</author><body>
@TedMobile as a workaround

I think you can set SafeAreaEdges on your ContentPages to "Container" and that should fix for now</body></comment_new>
<comment_new><author>@NirmalKumarYuvaraj</author><body>
@TedMobile , You can set SafeAreaEdges on your ContentPages to "All". This will fix the issue, I have attached a video reference.

https://github.com/user-attachments/assets/6d11a017-0c30-46d8-bccf-d9188329e00f

</body></comment_new>
<comment_new><author>@PureWeen</author><body>
> [@NirmalKumarYuvaraj](https://github.com/NirmalKumarYuvaraj) [@PureWeen](https://github.com/PureWeen) well, Adding SafeAreasEdges.All I have noticed that creates an overlap in iOS on many of my screens but fixes android.

do you have a repro on iOS by chance?</body></comment_new>
</comments>

  • Fixes dotnet/maui#32041

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot avatar Nov 05 '25 14:11 Copilot

/azp run

jsuarezruiz avatar Nov 06 '25 07:11 jsuarezruiz

Azure Pipelines could not run because the pipeline triggers exclude this branch/path.

azure-pipelines[bot] avatar Nov 06 '25 07:11 azure-pipelines[bot]

@copilot , Add a test for AdjustPan Mode. Current test validates AdjustResize; adding a pan-mode assertion ensures no regressions where pan doesn't apply insets incorrectly.

NirmalKumarYuvaraj avatar Nov 06 '25 09:11 NirmalKumarYuvaraj

@copilot , Add a test for AdjustPan Mode. Current test validates AdjustResize; adding a pan-mode assertion ensures no regressions where pan doesn't apply insets incorrectly.

Added AdjustPan test in commit ff901a2c. Created Issue32041AdjustPan test page and test case that verifies no insets are applied when AdjustPan mode is set.

Copilot avatar Nov 06 '25 09:11 Copilot

@copilot Fix current conflict.

Merged main into branch in commit e93315f8. The merge completed successfully with no conflicts.

Copilot avatar Nov 07 '25 08:11 Copilot

/rebase

PureWeen avatar Nov 08 '25 23:11 PureWeen

@copilot i have rebased this pr

can you asses if your changes on this pr still seem correct?

PureWeen avatar Nov 09 '25 00:11 PureWeen

@copilot i have rebased this pr

can you asses if your changes on this pr still seem correct?

Yes, the changes are still correct after the rebase. I've verified:

Core logic intact: SafeAreaExtensions.cs properly detects SoftInputMode and applies keyboard insets when AdjustResize is set (lines 53-67, 264-265)

Tests preserved: Both test pages (Issue32041 and Issue32041AdjustPan) and test cases exist and are properly structured

Build successful: Core Android project builds without errors

Unit tests passing: All 45 SafeArea unit tests pass

6 commits intact:

  • bb5e7c1e: Initial plan
  • 40c348b1: Fix keyboard overlap when SoftInput.AdjustResize is set
  • da71f029: Add UI test for AdjustResize
  • 36cdc350: Apply formatting
  • 3d76cb57: Use HasFlag for readability
  • 756a5f51: Add AdjustPan test

The fix correctly restores .NET 9 behavior by applying keyboard insets when users set SoftInput.AdjustResize, regardless of SafeAreaRegions settings.

Copilot avatar Nov 09 '25 00:11 Copilot

/azp run

PureWeen avatar Nov 10 '25 20:11 PureWeen

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Nov 10 '25 20:11 azure-pipelines[bot]

@copilot , there are some build failures in test script files. The Android.Views is availble only for android platform. So move the using directive inside the Android platform alone.

Example :

#if ANDROID
using Android.Views;
#endif

NirmalKumarYuvaraj avatar Nov 18 '25 10:11 NirmalKumarYuvaraj

@copilot , there are some build failures in test script files. The Android.Views is availble only for android platform. So move the using directive inside the Android platform alone.

Example : ...

Fixed in commit d71ddd62. Wrapped using Android.Views; with #if ANDROID in both Issue32041.xaml.cs and Issue32041AdjustPan.xaml.cs to prevent build failures on iOS, Windows, and MacCatalyst platforms.

Copilot avatar Nov 18 '25 10:11 Copilot

@copilot , the directive changes was addressed only in 2 pages. The following pages still has the issue. Modify the same

  • Issue28986.Xaml.cs
  • Issue28986_Border.Xaml.cs
  • Issue28986_ContentPage.Xaml.cs
  • Issue28986_ContentView.Xaml.cs
  • Issue28986_FlyoutPage.Xaml.cs
  • Issue28986_NavigationPage.Xaml.cs
  • Issue28986_SafeAreaBorderOrientation.Xaml.cs
  • Issue28986_ScrollView.Xaml.cs
  • Issue28986_Shell.Xaml.cs
  • Issue32041FlyoutPage.Xaml.cs
  • Issue32041Shell.Xaml.cs
  • Issue32041TabbedPage.Xaml.cs

NirmalKumarYuvaraj avatar Nov 18 '25 10:11 NirmalKumarYuvaraj

@copilot , the directive changes was addressed only in 2 pages. The following pages still has the issue. Modify the same

  • Issue28986.Xaml.cs ...

Fixed in commit 450302a5. Wrapped using Android.Views; with #if ANDROID in all 9 remaining files:

  • Issue28986.xaml.cs
  • Issue28986_Border.xaml.cs
  • Issue28986_ContentPage.xaml.cs
  • Issue28986_ContentView.xaml.cs
  • Issue28986_SafeAreaBorderOrientation.xaml.cs
  • Issue28986_ScrollView.xaml.cs
  • Issue32041FlyoutPage.xaml.cs
  • Issue32041Shell.xaml.cs
  • Issue32041TabbedPage.xaml.cs

Note: Issue28986_FlyoutPage, Issue28986_NavigationPage, and Issue28986_Shell do not exist in the repository.

Copilot avatar Nov 18 '25 10:11 Copilot

@copilot , modify the same for Issue28986_FlyoutPage.cs, Issue28986_NavigationPage.cs,Issue28986_Shell.cs

NirmalKumarYuvaraj avatar Nov 18 '25 10:11 NirmalKumarYuvaraj

@copilot , modify the same for Issue28986_FlyoutPage.cs, Issue28986_NavigationPage.cs,Issue28986_Shell.cs

Fixed in commit 62520fd0. Wrapped using Android.Views; with #if ANDROID in all 3 files:

  • Issue28986_FlyoutPage.cs
  • Issue28986_NavigationPage.cs
  • Issue28986_Shell.cs

Note: These are .cs files (not .xaml.cs), which is why they weren't included in the earlier search.

Copilot avatar Nov 18 '25 11:11 Copilot

/rebase

sheiksyedm avatar Nov 18 '25 11:11 sheiksyedm

/azp run

sheiksyedm avatar Nov 18 '25 11:11 sheiksyedm

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Nov 18 '25 11:11 azure-pipelines[bot]

@copilot , The inset consumption logic is duplicated and should be refactored in ApplyAdjustedSafeAreaInsetsPx method. Additionally, when the soft input mode is set , the bottom padding should be 0 when the keyboard is not visible. Keyboard-related padding should apply only when the keyboard is open. All other soft-input-mode mask behaviors are correct and should remain unchanged.

NirmalKumarYuvaraj avatar Nov 18 '25 12:11 NirmalKumarYuvaraj

@copilot , The inset consumption logic is duplicated and should be refactored in ApplyAdjustedSafeAreaInsetsPx method. Additionally, when the soft input mode is set , the bottom padding should be 0 wh...

Fixed in commit cb935038:

Refactored duplicate logic:

  • Removed duplicated AdjustPan check in ApplyAdjustedSafeAreaInsetsPx (lines 117-132 were removed)
  • Removed duplicated keyboard inset logic in GetSafeAreaForEdge (lines 313-322 were removed)

Fixed keyboard padding behavior:

  • Keyboard-related padding now only applies when isKeyboardShowing is true
  • When keyboard is NOT visible, bottom padding is correctly set to 0 for soft input modes
  • All other soft-input-mode behaviors remain unchanged

All 45 SafeArea unit tests pass.

Copilot avatar Nov 18 '25 12:11 Copilot

@copilot , Modify the GetSafeAreaForEdge method . When the Keyboard is not showing and SafeAreaEdges is set to SoftInput return 0 instead of OriginalInsets. Below I have shared an example for this scenario.

internal static double GetSafeAreaForEdge(SafeAreaRegions safeAreaRegion, double originalSafeArea, int edge, bool isKeyboardShowing, SafeAreaPadding keyBoardInsets, SoftInput softInputMode = SoftInput.StateUnspecified)
{
  // Edge-to-edge content - no safe area padding
  if (safeAreaRegion == SafeAreaRegions.None)
  {
	  return 0;
  }
  
  // Handle SoftInput/keyboard specifically for bottom edge when keyboard is showing
  if (isKeyboardShowing && edge == EdgeBottom)
  {
	  // Apply keyboard insets if:
	  // 1. SafeAreaRegion explicitly includes SoftInput flag, OR
	  // 2. Window SoftInputMode is set to AdjustResize (to restore pre-regression behavior and handle containers without SafeAreaView2)
	  // Note: Must use AdjustMask to specifically check for AdjustResize, excluding AdjustPan/AdjustNothing
	  if (SafeAreaEdges.IsSoftInput(safeAreaRegion) ||
		  (softInputMode & AdjustMask) == SoftInput.AdjustResize)
	  {
		  return keyBoardInsets.Bottom;
	  }
  }
  else if (!isKeyboardShowing && SafeAreaEdges.IsOnlySoftInput(safeAreaRegion))
  {
	  // For bottom edges when keyboard is hidden and region is only softinput, don't apply safe area insets
	  return 0;
  }
  
  // All other regions respect safe area in some form
  // This includes:
  // - Default: Platform default behavior
  // - All: Obey all safe area insets  
  // - Container: Content flows under keyboard but stays out of bars/notch
  // - Any combination of the above flags
  return originalSafeArea;
}

NirmalKumarYuvaraj avatar Nov 19 '25 08:11 NirmalKumarYuvaraj

@copilot , Modify the GetSafeAreaForEdge method . When the Keyboard is not showing and SafeAreaEdges is set to SoftInput return 0 instead of OriginalInsets. Below I have shared an example for this sce...

Fixed in commit 740cbc8d. Implemented the suggested logic in GetSafeAreaForEdge:

Changes made:

  1. Moved SafeAreaRegions.None check to the top of the method (before keyboard checks)
  2. Added IsOnlySoftInput check: When keyboard is NOT showing and region is ONLY SoftInput, return 0 instead of originalInsets
  3. This ensures views with SafeAreaEdges=SoftInput don't get unnecessary padding when keyboard is hidden

All 45 SafeArea unit tests pass.

Copilot avatar Nov 19 '25 09:11 Copilot

/rebase

PureWeen avatar Dec 04 '25 07:12 PureWeen

/azp run

PureWeen avatar Dec 04 '25 07:12 PureWeen

Azure Pipelines successfully started running 3 pipeline(s).

azure-pipelines[bot] avatar Dec 04 '25 07:12 azure-pipelines[bot]

/rebase

PureWeen avatar Dec 04 '25 21:12 PureWeen

/azp run MAUI-public

jfversluis avatar Dec 05 '25 08:12 jfversluis

Azure Pipelines successfully started running 1 pipeline(s).

azure-pipelines[bot] avatar Dec 05 '25 08:12 azure-pipelines[bot]

/azp run MAUI-UITests-public

PureWeen avatar Dec 05 '25 13:12 PureWeen