Skip to content

[Android] Keyboard: Fix inset handling for Window SoftInput modes#33902

Open
NirmalKumarYuvaraj wants to merge 8 commits intodotnet:mainfrom
NirmalKumarYuvaraj:Keyboard_SafeArea_Temp
Open

[Android] Keyboard: Fix inset handling for Window SoftInput modes#33902
NirmalKumarYuvaraj wants to merge 8 commits intodotnet:mainfrom
NirmalKumarYuvaraj:Keyboard_SafeArea_Temp

Conversation

@NirmalKumarYuvaraj
Copy link
Copy Markdown
Contributor

@NirmalKumarYuvaraj NirmalKumarYuvaraj commented Feb 5, 2026

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

This pull request addresses issues with keyboard overlap and safe area handling on Android when using different SoftInput modes (AdjustResize and AdjustPan). It introduces new test cases, improves platform-specific logic for keyboard and safe area insets, and enhances the UI test infrastructure for more accurate validation of layout changes when the keyboard appears or disappears.

The most important changes are:

Android Keyboard and Safe Area Handling Improvements:

  • Refactored and enhanced the MauiWindowInsetListener to properly handle keyboard insets for AdjustResize and AdjustPan modes. This includes applying or resetting bottom padding on the CoordinatorLayout and its descendants based on the keyboard state and soft input mode, ensuring no double padding and correct layout restoration when the keyboard is shown or hidden. [1] [2] [3]
  • Removed redundant keyboard inset handling from SafeAreaExtensions.cs to centralize logic in MauiWindowInsetListener, preventing conflicts and ensuring consistent behavior.

Test Cases and Validation:

  • Added a new test page (Issue32041.xaml and code-behind) to verify that the keyboard does not overlap input fields when SoftInput.AdjustResize is set, and that the layout resizes appropriately. [1] [2]
  • Added a comprehensive UI test (Issue32041.cs) that measures and asserts the movement of UI elements when the keyboard appears/disappears, ensuring the fix works as intended.
  • Enhanced the existing AdjustPan test page and test (Issue32041AdjustPan.xaml, Issue32041AdjustPan.cs) with more precise automation IDs and improved assertions for layout and element visibility during keyboard transitions. [1] [2] [3] [4]

Test Infrastructure Enhancements:

  • Added a new helper method GetAndroidSystemBarInsets to UITest.Appium.HelperExtensions for accurate retrieval of status and navigation bar heights in Android UI tests, allowing for precise layout assertions.
  • Minor change to the visibility of GetSystemBars for internal use.

Dependency Updates:

  • Added missing using directive for AndroidX.CoordinatorLayout.Widget to support new logic.

These changes collectively ensure that the app's content is correctly resized or panned in response to the keyboard on Android, and that UI tests can reliably validate this behavior.

Issues Fixed

Fixes #32041

SoftInputMode API 30 API 36
AdjustNothing
AdjustNothing.mov
AdjustNothing.mov
AdjustResize
AdjustResize.mov
AdjustResize.mov
AdjustPan
AdjustPan.mov
AdjustPan.mov
TabbedPage + AdjustResize
API.30.mov
API.36.mov

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Feb 5, 2026
@NirmalKumarYuvaraj NirmalKumarYuvaraj added platform/android area-safearea Issues/PRs that have to do with the SafeArea functionality community ✨ Community Contribution labels Feb 5, 2026
@NirmalKumarYuvaraj NirmalKumarYuvaraj marked this pull request as ready for review February 6, 2026 04:18
Copilot AI review requested due to automatic review settings February 6, 2026 04:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses keyboard overlap and safe area handling issues on Android by refactoring how keyboard insets are managed for different WindowSoftInputModeAdjust modes (AdjustResize, AdjustPan, AdjustNothing). The fix centralizes keyboard inset handling in MauiWindowInsetListener by detecting the active SoftInputMode and applying appropriate padding to the CoordinatorLayout while managing child view padding to prevent double-padding issues.

Changes:

  • Refactored MauiWindowInsetListener to handle keyboard insets based on SoftInputMode, applying bottom padding for AdjustResize and consuming insets for AdjustPan to prevent layout conflicts
  • Removed redundant keyboard handling logic from SafeAreaExtensions.cs to centralize behavior in MauiWindowInsetListener
  • Added new helper method GetAndroidSystemBarInsets() to test infrastructure for accurate system bar measurement in UI tests
  • Created comprehensive UI test pages and tests for both AdjustResize and AdjustPan modes to validate keyboard behavior

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/Core/src/Platform/Android/MauiWindowInsetListener.cs Added keyboard inset handling logic based on SoftInputMode; handles CoordinatorLayout padding and child view padding reset/restoration for AdjustResize and AdjustPan modes
src/Core/src/Platform/Android/SafeAreaExtensions.cs Removed redundant AdjustPan keyboard handling logic to consolidate in MauiWindowInsetListener
src/TestUtils/src/UITest.Appium/HelperExtensions.cs Added GetAndroidSystemBarInsets() helper method and changed GetSystemBars() to internal visibility
src/Controls/tests/TestCases.HostApp/Issues/Issue32041.xaml Created test page for AdjustResize mode with visual markers to verify keyboard behavior
src/Controls/tests/TestCases.HostApp/Issues/Issue32041.xaml.cs Code-behind that sets SoftInput.AdjustResize mode for the test page
src/Controls/tests/TestCases.HostApp/Issues/Issue32041AdjustPan.xaml Enhanced existing AdjustPan test page with additional AutomationIds for precise testing
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041.cs UI test validating AdjustResize behavior measures element movement when keyboard shows/hides
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041AdjustPan.cs Enhanced UI test for AdjustPan mode with improved assertions for layout and visibility

Comment thread src/Core/src/Platform/Android/MauiWindowInsetListener.cs Outdated
Comment thread src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041.cs Outdated
Comment thread src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041.cs Outdated
Comment thread src/Core/src/Platform/Android/MauiWindowInsetListener.cs Outdated
Comment thread src/Core/src/Platform/Android/MauiWindowInsetListener.cs Outdated
Comment thread src/Core/src/Platform/Android/MauiWindowInsetListener.cs Outdated
@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests, maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@PureWeen
Copy link
Copy Markdown
Member

PureWeen commented Feb 9, 2026

/rebase

@github-actions github-actions Bot force-pushed the Keyboard_SafeArea_Temp branch from 3b29a8a to 697d237 Compare February 9, 2026 22:45
@PureWeen
Copy link
Copy Markdown
Member

🤖 CI Test Feedback

We ran the Issue32041 tests on an Android API 30 emulator (matching the standard maui-pr UI test pipeline) and got the following results:

Test Result Details
VerifyContainerDoesNotResizeWithAdjustPan ✅ Pass
VerifyTabbedPageWithKeyboard ✅ Pass
VerifyContainerResizesWithAdjustResize ❌ Fail NullReferenceException in HelperExtensions.GetRect()

The failing test hits a NullReferenceException at Issue32041.cs:line 40 — the element cannot be found after the keyboard appears, likely because the layout has not settled yet.

Suggestion: Add App.WaitForElement() before calling GetRect() on elements accessed after keyboard show/hide transitions. For example:

// Before
var rect = App.FindElement("BottomMarker").GetRect();

// After  
App.WaitForElement("BottomMarker");
var rect = App.FindElement("BottomMarker").GetRect();

This is a common Appium timing issue on emulators where layout changes from keyboard transitions may not be immediately reflected.

@NirmalKumarYuvaraj NirmalKumarYuvaraj changed the title [Android] Fixed WindowSoftInputMode + Keyboard related issues [Android] Keyboard: Fix inset handling for Window SoftInput modes Feb 10, 2026
@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests, maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@rmarinho rmarinho added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Feb 18, 2026
@PureWeen PureWeen modified the milestone: .NET 10 SR5 Feb 23, 2026
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues and removed s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) labels Apr 6, 2026
@PureWeen PureWeen modified the milestones: .NET 10 SR6, .NET 10 SR7 Apr 14, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 22, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 23, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 23, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please review the ai's summary?

@dotnet dotnet deleted a comment from MauiBot Apr 24, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 24, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 25, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Apr 25, 2026

🤖 AI Summary

👋 @NirmalKumarYuvaraj — new AI review results are available. Please review the latest session below.

📊 Review Sessionc72a865 · refactor maui windowinsetlistener · 2026-04-25 13:03 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ⚠️ ENV ERROR

Platform: ANDROID · Base: main · Merge base: 388b82f1

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue32041 Issue32041 ✅ FAIL — 609s ❌ FAIL — 588s
🖥️ Issue32041AdjustPan Issue32041AdjustPan ⚠️ ENV ERROR ⚠️ ENV ERROR
🖥️ Issue32041FlyoutPage Issue32041FlyoutPage ⚠️ ENV ERROR ⚠️ ENV ERROR
🖥️ Issue32041Shell Issue32041Shell ⚠️ ENV ERROR ⚠️ ENV ERROR
🖥️ Issue32041TabbedPage Issue32041TabbedPage ⚠️ ENV ERROR ⚠️ ENV ERROR
🔴 Without fix — 🖥️ Issue32041: FAIL ✅ · 609s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:06:48.20
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.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.14]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.50]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 5 of 5 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/25/2026 11:46:52 FixtureSetup for Issue32041(Android)
>>>>> 04/25/2026 11:46:55 VerifyContainerResizesWithAdjustResize Start
>>>>> 04/25/2026 11:47:16 VerifyContainerResizesWithAdjustResize Stop
>>>>> 04/25/2026 11:47:16 Log types: logcat, bugreport, server
  Failed VerifyContainerResizesWithAdjustResize [21 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.TestCases.Tests.Issues.Issue32041.VerifyContainerResizesWithAdjustResize() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041.cs:line 40
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

>>>>> 04/25/2026 11:47:20 FixtureSetup for Issue32041AdjustPan(Android)
>>>>> 04/25/2026 11:47:24 VerifyContainerDoesNotResizeWithAdjustPan Start
>>>>> 04/25/2026 11:47:30 VerifyContainerDoesNotResizeWithAdjustPan Stop
  Passed VerifyContainerDoesNotResizeWithAdjustPan [5 s]
>>>>> 04/25/2026 11:47:31 FixtureSetup for Issue32041FlyoutPage(Android)
>>>>> 04/25/2026 11:47:36 FlyoutPageContainerResizesWithAdjustResize Start
>>>>> 04/25/2026 11:47:40 FlyoutPageContainerResizesWithAdjustResize Stop
>>>>> 04/25/2026 11:47:41 Log types: logcat, bugreport, server
  Failed FlyoutPageContainerResizesWithAdjustResize [4 s]
  Error Message:
     FlyoutPage detail container should resize (height decrease) when keyboard appears with AdjustResize. Before: 1710px, After: 1710px
Assert.That(resizedHeight, Is.LessThan(initialHeight))
  Expected: less than 1710
  But was:  1710

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue32041FlyoutPage.FlyoutPageContainerResizesWithAdjustResize() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041FlyoutPage.cs:line 39

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue32041FlyoutPage.FlyoutPageContainerResizesWithAdjustResize() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041FlyoutPage.cs:line 39


>>>>> 04/25/2026 11:47:44 FixtureSetup for Issue32041Shell(Android)
>>>>> 04/25/2026 11:47:49 ShellContainerResizesWithAdjustResize Start
>>>>> 04/25/2026 11:47:53 ShellContainerResizesWithAdjustResize Stop
  Passed ShellContainerResizesWithAdjustResize [4 s]
>>>>> 04/25/2026 11:47:56 FixtureSetup for Issue32041TabbedPage(Android)
>>>>> 04/25/2026 11:48:01 VerifyTabbedPageWithKeyboard Start
>>>>> 04/25/2026 11:48:20 VerifyTabbedPageWithKeyboard Stop
>>>>> 04/25/2026 11:48:20 Log types: logcat, bugreport, server
  Failed VerifyTabbedPageWithKeyboard [19 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.TestCases.Tests.Issues.Issue32041TabbedPage.VerifyTabbedPageWithKeyboard() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041TabbedPage.cs:line 35
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

NUnit Adapter 4.5.0.0: Test execution complete

Test Run Failed.
Total tests: 5
     Passed: 2
     Failed: 3
 Total time: 1.7106 Minutes

🟢 With fix — 🖥️ Issue32041: FAIL ❌ · 588s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:06:50.22
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
  Determining projects to restore...
  All projects are up-to-date for restore.
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.13937179
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.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.11]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.42]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 5 of 5 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/25/2026 11:56:58 FixtureSetup for Issue32041(Android)
>>>>> 04/25/2026 11:57:02 VerifyContainerResizesWithAdjustResize Start
>>>>> 04/25/2026 11:57:08 VerifyContainerResizesWithAdjustResize Stop
  Passed VerifyContainerResizesWithAdjustResize [6 s]
>>>>> 04/25/2026 11:57:10 FixtureSetup for Issue32041AdjustPan(Android)
>>>>> 04/25/2026 11:57:14 VerifyContainerDoesNotResizeWithAdjustPan Start
>>>>> 04/25/2026 11:57:20 VerifyContainerDoesNotResizeWithAdjustPan Stop
  Passed VerifyContainerDoesNotResizeWithAdjustPan [6 s]
>>>>> 04/25/2026 11:57:22 FixtureSetup for Issue32041FlyoutPage(Android)
>>>>> 04/25/2026 11:57:27 FlyoutPageContainerResizesWithAdjustResize Start
>>>>> 04/25/2026 11:57:31 FlyoutPageContainerResizesWithAdjustResize Stop
  Passed FlyoutPageContainerResizesWithAdjustResize [4 s]
>>>>> 04/25/2026 11:57:34 FixtureSetup for Issue32041Shell(Android)
>>>>> 04/25/2026 11:57:39 ShellContainerResizesWithAdjustResize Start
>>>>> 04/25/2026 11:57:42 ShellContainerResizesWithAdjustResize Stop
  Passed ShellContainerResizesWithAdjustResize [4 s]
>>>>> 04/25/2026 11:57:45 FixtureSetup for Issue32041TabbedPage(Android)
>>>>> 04/25/2026 11:57:50 VerifyTabbedPageWithKeyboard Start
>>>>> 04/25/2026 11:58:09 VerifyTabbedPageWithKeyboard Stop
>>>>> 04/25/2026 11:58:09 Log types: logcat, bugreport, server
  Failed VerifyTabbedPageWithKeyboard [20 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.TestCases.Tests.Issues.Issue32041TabbedPage.VerifyTabbedPageWithKeyboard() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue32041TabbedPage.cs:line 35
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.RuntimeMethodHandle.InvokeMethod(ObjectHandleOnStack target, Void** arguments, ObjectHandleOnStack sig, BOOL isConstructor, ObjectHandleOnStack result)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)

NUnit Adapter 4.5.0.0: Test execution complete

Test Run Failed.
Total tests: 5
     Passed: 4
     Failed: 1
 Total time: 1.4018 Minutes

🔴 Without fix — 🖥️ Issue32041AdjustPan: ⚠️ ENV ERROR · 0s

Log file empty

🟢 With fix — 🖥️ Issue32041AdjustPan: ⚠️ ENV ERROR · 0s

Log file empty

🔴 Without fix — 🖥️ Issue32041FlyoutPage: ⚠️ ENV ERROR · 0s

Log file empty

🟢 With fix — 🖥️ Issue32041FlyoutPage: ⚠️ ENV ERROR · 0s

Log file empty

🔴 Without fix — 🖥️ Issue32041Shell: ⚠️ ENV ERROR · 0s

Log file empty

🟢 With fix — 🖥️ Issue32041Shell: ⚠️ ENV ERROR · 0s

Log file empty

🔴 Without fix — 🖥️ Issue32041TabbedPage: ⚠️ ENV ERROR · 0s

Log file empty

🟢 With fix — 🖥️ Issue32041TabbedPage: ⚠️ ENV ERROR · 0s

Log file empty

⚠️ Issues found
  • ⚠️ Issue32041AdjustPan without fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
  • ⚠️ Issue32041FlyoutPage without fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
  • ⚠️ Issue32041Shell without fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
  • ⚠️ Issue32041TabbedPage without fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
  • Issue32041 FAILED with fix (should pass)
    • Device tests: 1 of 5 failed
  • ⚠️ Issue32041AdjustPan with fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
  • ⚠️ Issue32041FlyoutPage with fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
  • ⚠️ Issue32041Shell with fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
  • ⚠️ Issue32041TabbedPage with fix: Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
📁 Fix files reverted (2 files)
  • src/Core/src/Platform/Android/MauiWindowInsetListener.cs
  • src/Core/src/Platform/Android/SafeAreaExtensions.cs

🔍 Pre-Flight — Context & Validation

Issue: #32041 - net 10 rc2 keyboard overlap android
PR: #33902 - [Android] Keyboard: Fix inset handling for Window SoftInput modes
Platforms Affected: Android only
Files Changed: 2 implementation, 13 test

Key Findings

  • Regression in .NET 10 RC2: SoftInput.AdjustResize stopped resizing content, causing keyboard to overlap Entry fields at bottom of screen
  • Root cause: Previous inset handling didn't correctly apply keyboard padding to the CoordinatorLayout for AdjustResize mode
  • Fix centralizes all keyboard inset logic in MauiWindowInsetListener, removing fragmented handling from SafeAreaExtensions.cs
  • Critical logic bug: ApplyKeyboardInsets return value is discarded — ApplyBottomNavViewInsets runs unconditionally after and overwrites the keyboard padding for bottom-nav scenarios
  • Incomplete keyboard-dismiss path: hasBottomNav == true branch does nothing on dismiss (commented-out code)
  • Gate FAILED — tests did not behave as expected during CI verification

Code Review Summary

Verdict: NEEDS_CHANGES
Confidence: medium
Errors: 1 | Warnings: 3 | Suggestions: 2

Key code review findings:

  • MauiWindowInsetListener.cs line ~236-238: ApplyKeyboardInsets return value discarded; ApplyBottomNavViewInsets immediately overwrites keyboard padding set for bottom-nav case
  • ⚠️ MauiWindowInsetListener.cs ~keyboard-dismiss branch: hasBottomNav == true path does nothing on keyboard dismiss — contentView retains stale keyboard-height bottom padding
  • ⚠️ MauiWindowInsetListener.cs ~AdjustPan branch: Consumes ALL insets (including system bars) while keyboard is visible — should only consume IME insets
  • ⚠️ Issue32041TabbedPage.cs: Duplicate AutomationId values ("MainContainer", "TopLabel", "BottomMarker", "TestEntry") across both tabs
  • 💡 Hardcoded 200px movement thresholds are fragile on small Helix emulators
  • 💡 VerifyContainerDoesNotResizeWithAdjustPan test name contradicts assertion body

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #33902 Centralize keyboard insets in MauiWindowInsetListener; apply CoordinatorLayout bottom padding for AdjustResize; consume IME insets for AdjustPan ❌ FAILED (Gate) MauiWindowInsetListener.cs, SafeAreaExtensions.cs Has logic bug: return value discarded; bottom-nav dismiss path incomplete

🔬 Code Review — Deep Analysis

Code Review — PR #33902

Independent Assessment

What this changes: Adds keyboard inset handling in MauiWindowInsetListener.ApplyKeyboardInsets for AdjustResize, AdjustPan, and AdjustNothing modes, adds a _wasKeyboardShowing guard to prevent double-application, removes keyboard handling from SafeAreaExtensions.cs (centralizing it), adds GetAndroidSystemBarInsets to HelperExtensions, and adds five new host-app pages + UI tests covering Issue 32041 across different navigation containers.

Inferred motivation: When SoftInput.AdjustResize is set, MAUI's existing inset pipeline was either double-applying padding or not resizing content correctly relative to the keyboard, causing the keyboard to overlap input fields.


Reconciliation with PR Narrative

Author claims: Refactors keyboard inset handling into MauiWindowInsetListener, removes redundant handling from SafeAreaExtensions.cs, adds comprehensive tests across content page, shell, tabbed page, flyout, and AdjustPan modes.

Agreement: The centralization approach is sound and follows the existing per-view registry pattern. The test coverage across navigation containers is thorough.

Disagreements / concerns: The ApplyKeyboardInsets return value is silently discarded (see ❌ below), and the AdjustPan inset-consuming behavior is overly aggressive. Several tests have assertions that may be fragile in CI.


Findings

❌ Error — ApplyKeyboardInsets return value is discarded; ApplyBottomNavViewInsets overwrites keyboard padding

MauiWindowInsetListener.cs, line 236–238:

ApplyKeyboardInsets(v, insets, bottomTabContainer, contentView, hasBottomNav, systemBars);  // return ignored
ApplyBottomNavViewInsets(systemBars, displayCutout, hasBottomNav, contentView);             // overwrites contentView

When AdjustResize + keyboard showing + hasBottomNav == true, ApplyKeyboardInsets sets contentView.SetPadding(..., bottomInset) where bottomInset = Math.Max(systemBars.Bottom, imeInsets.Bottom) (roughly the keyboard height). Then ApplyBottomNavViewInsets immediately runs and sets contentView.SetPadding(0, 0, 0, Math.Max(systemBars.Bottom, displayCutout.Bottom)) — just the nav-bar height — overwriting the keyboard padding.

If correctness in the Shell+bottom-tabs case (Issue32041Shell) depends on that padding being preserved through this pipeline, it won't be. The discarded WindowInsetsCompat.Consumed result is also silent — callers of OnApplyWindowInsets see the return from ApplyDefaultWindowInsets, not from ApplyKeyboardInsets. Consider: (a) checking the return value and short-circuiting, or (b) restructuring so ApplyBottomNavViewInsets is skipped when ApplyKeyboardInsets consumed the insets.


⚠️ Warning — Commented-out code leaves bottom-tabs + keyboard-dismiss path incomplete

MauiWindowInsetListener.cs, inside the AdjustResize keyboard-dismiss branch:

else if (!isKeyboardShowing && _wasKeyboardShowing && !IsImeAnimating)
{
    _wasKeyboardShowing = false;
    if (hasBottomNav)
    {
        //RequestInsetsForDescendants(contentView);  // ← dead code, no explanation
    }
    else
    {
        coordinatorLayout.SetPadding(0, 0, 0, 0);
        coordinatorLayout.Post(() => RequestInsetsForDescendants(coordinatorLayout));
    }
}

For the hasBottomNav == true path, keyboard dismissal does nothing beyond resetting the flag. The non-bottom-nav path explicitly zeros padding and re-requests insets. The commented line is unexplained. If contentView's stale bottom padding is not restored after keyboard dismissal, it will cause a visual layout issue.


⚠️ Warning — AdjustPan consumes ALL insets (not just IME) while keyboard is visible

MauiWindowInsetListener.cs, line ~412–416:

else if (adjustMode == SoftInput.AdjustPan)
{
    if (isKeyboardShowing && !IsImeAnimating)
    {
        return WindowInsetsCompat.Consumed;
    }
}

This blanket-consumes all inset types (system bars, display cutout, IME) while the keyboard is visible in AdjustPan mode. Status-bar and notch safe-area insets would be suppressed from reaching child views, potentially causing the status bar to overlap content on the top edge while the keyboard is visible. Should only consume the IME inset, not system bars.


⚠️ Warning — Duplicate AutomationId values across tabs in Issue32041TabbedPage

Issue32041TabbedPage.csCreateContentPage is called twice and both pages receive identical AutomationId values: "MainContainer", "TopLabel", "BottomMarker", "TestEntry". Appium element lookups by AutomationId are not guaranteed to return the active tab's element when duplicates exist.


💡 Suggestion — Hardcoded 200px thresholds are fragile

Issue32041.cs, Issue32041Shell.cs, Issue32041FlyoutPage.cs tests assert upwardMovement/heightReduction > 200. On smaller Helix emulators, the software keyboard may be shorter than 200px. Consider proportional threshold or deriving from actual IME inset height.


💡 Suggestion — VerifyContainerDoesNotResizeWithAdjustPan name contradicts test body

Issue32041AdjustPan.cs: Test name says "DoesNotResize" but body asserts afterBottom < initialBottom (bottom marker moves up). Name should be updated to match actual tested behavior.


CI Status

⚠️ CI is FAILING. Multiple reviewers have commented that tests are failing. Helix unit test failures exist that need to be triaged before merge.


Blast Radius

  • All Android apps using SoftInput.AdjustResize — directly impacted; this changes the bottom padding logic for the entire CoordinatorLayout when keyboard appears.
  • All Android apps using SoftInput.AdjustPanSafeAreaExtensions.cs AdjustPan handling removed; keyboard inset is now consumed at a different point.
  • Apps with Shell bottom tabs — may be affected by the execution-order bug where ApplyBottomNavViewInsets overwrites keyboard padding.
  • No iOS/Windows impact — changes are pure Android platform code.

Failure-Mode Probes

  1. AdjustResize + Shell bottom tabs: ApplyKeyboardInsets sets contentView padding to keyboard height, then ApplyBottomNavViewInsets overwrites it with nav-bar height only → keyboard still overlaps content in Shell scenarios.
  2. AdjustResize + no bottom nav: coordinatorLayout.SetPadding(0,0,0, bottomInset) — then on dismiss, resets to (0,0,0,0) and re-requests insets — this path looks correct.
  3. AdjustPan + keyboard visible: IME insets AND system bar insets consumed → status bar area may show behind content edge.
  4. Keyboard dismiss with bottom nav: Does nothing (commented-out code) → contentView retains stale keyboard-height bottom padding → layout visually broken until next inset cycle.

Verdict: NEEDS_CHANGES

Confidence: medium

Key issues:

  1. ApplyKeyboardInsets return value discarded — ApplyBottomNavViewInsets overwrites keyboard padding.
  2. ⚠️ Commented-out keyboard-dismiss path for bottom-nav leaves layout in broken state.
  3. ⚠️ AdjustPan over-consumes insets (system bars too, not just IME).
  4. CI is currently failing.

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Keyboard-Aware Bottom Nav Padding (Single Point of Truth) — integrate keyboard awareness into existing bottom-nav padding logic; contentView padding = max(navBarHeight, keyboardHeight) when AdjustResize+keyboard visible; no separate ApplyKeyboardInsets method ✅ PASS 1 file (MauiWindowInsetListener.cs) No separate method; single decision point
2 try-fix (claude-sonnet-4.6) IME-Aware contentView as Single Padding Authority — contentView padding = isKeyboardShowing ? max(systemBottom, imeBottom) : systemBottom; no explicit dismiss-path needed since system calls OnApplyWindowInsets on every IME state change ✅ PASS 1 file (MauiWindowInsetListener.cs) Minimal change; most elegant; relies on Android inset dispatch naturally
3 try-fix (gpt-5.3-codex) Insets Handoff with IME-Only Consumption — kept decomposed methods but fixed ordering (bottom-nav first, then keyboard can override); IME-only consumption for AdjustPan (not all insets) ✅ PASS 1 file (MauiWindowInsetListener.cs) Closest to PR structure but with ordering fixed
4 try-fix (gpt-5.4) Dispatch-time IME normalization in OnApplyWindowInsets ❌ FAIL 1 file Inset rewriting insufficient; geometry assertions failed
PR PR #33902 Centralize keyboard insets in MauiWindowInsetListener; separate ApplyKeyboardInsets method; remove AdjustPan handling from SafeAreaExtensions ❌ FAILED (Gate) 2 files ApplyKeyboardInsets return value discarded; ApplyBottomNavViewInsets overwrites keyboard padding

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 Yes Animation-Callback-Only: move keyboard padding into WindowInsetsAnimationCompat.Callback OnStart/OnProgress/OnEnd for smooth animated resize
claude-sonnet-4.6 2 Yes Spacer-view: append invisible spacer view as last child whose height = max(navBarHeight, keyboardHeight), eliminating all SetPadding conflicts
gpt-5.3-codex 2 Yes Insets state machine: Hidden→Showing→Visible→Hiding with monotonic IME updates and bottom margin instead of padding
gpt-5.4 2 Yes Mode-switch: use WindowCompat.SetDecorFitsSystemWindows(window, true) for AdjustResize to use native Android resize

Cross-pollination ideas are more complex; given 3 passing candidates already, additional exploration not warranted.

Exhausted: Yes (all 4 models queried, cross-pollination round completed)
Selected Fix: Candidate #2 (claude-sonnet-4.6) — IME-Aware contentView as Single Padding Authority

Reason: Most minimal change (60 lines, 1 file), relies on Android's natural inset dispatch to handle dismiss path without explicit state management, single expression eliminates the padding overwrite race condition entirely. Candidate #1 also passes but is larger; Candidate #3 keeps the decomposed-method structure closest to PR but requires careful ordering. Candidate #2 is the simplest correct solution.


📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #32041 — Android AdjustResize keyboard overlap regression in .NET 10 RC2
Code Review NEEDS_CHANGES (medium) 1 error, 3 warnings
Gate ❌ FAILED Android — tests did not behave as expected
Try-Fix ✅ COMPLETE 4 attempts, 3 passing (Candidates #1, #2, #3)
Report ✅ COMPLETE

Code Review Impact on Try-Fix

The code-review ❌ Error (discarded ApplyKeyboardInsets return value; ApplyBottomNavViewInsets overwrites keyboard padding) was the central finding that guided all three successful fix attempts. Each model independently identified the "two writers for contentView.PaddingBottom" race condition as the root problem and resolved it via different architectural approaches:

  • Candidate [Draft] Readme WIP #1 eliminated the separate ApplyKeyboardInsets method entirely (single inline computation)
  • Candidate Update README.md #2 used a single IME-aware expression for contentView padding in the existing bottom-nav path
  • Candidate Third #3 fixed execution ordering between the two methods

The ⚠️ Warning about AdjustPan consuming all insets was addressed in Candidate #3 (IME-only consumption). The incomplete keyboard-dismiss path warning was addressed in Candidates #1 and #3.

Summary

PR #33902 fixes a real regression in .NET 10 RC2 where SoftInput.AdjustResize stopped resizing content above the keyboard on Android. The centralization approach (moving keyboard inset logic to MauiWindowInsetListener, removing fragmented handling from SafeAreaExtensions) is architecturally sound. However, the implementation has a correctness bug: ApplyKeyboardInsets is called but its return value is discarded, and ApplyBottomNavViewInsets unconditionally runs afterward, overwriting the keyboard padding in the bottom-nav case. Additionally, the keyboard-dismiss path for hasBottomNav==true does nothing (commented-out code), leaving stale padding after keyboard dismissal.

Gate failed, and Try-Fix found 3 simpler alternative fixes that pass the test. The recommended fix is Candidate #2 — the minimal IME-aware single-expression approach that eliminates the padding race without adding new state tracking.

Root Cause

ApplyDefaultWindowInsets calls ApplyKeyboardInsets (which correctly sets contentView padding to keyboard height) then immediately calls ApplyBottomNavViewInsets (which unconditionally sets contentView padding to nav-bar height only), overwriting the keyboard padding. The return value of ApplyKeyboardInsets (which returns WindowInsetsCompat.Consumed when handled) is discarded, so the bottom-nav path has no knowledge of whether keyboard handling already occurred.

Fix Quality

The PR's fix approach direction is correct — centralizing keyboard inset handling in MauiWindowInsetListener is the right architectural move. However, the execution has multiple issues:

  1. Critical: Discarded return value + ApplyBottomNavViewInsets overwriting keyboard padding in the bottom-nav case
  2. Medium: Incomplete keyboard-dismiss path for hasBottomNav==true (commented-out restoration)
  3. Low: AdjustPan branch consumes all insets instead of only IME insets
  4. Test quality: Duplicate AutomationId values across TabbedPage tabs; hardcoded 200px thresholds

Recommended fix (Candidate #2): Replace the separate ApplyKeyboardInsets method with a single IME-aware expression in the existing bottom-nav padding block:

var systemBottomInset = Math.Max(systemBars?.Bottom ?? 0, displayCutout?.Bottom ?? 0);
var bottomInset = isKeyboardShowing
    ? Math.Max(systemBottomInset, imeInsets?.Bottom ?? 0)
    : systemBottomInset;
contentView?.SetPadding(0, 0, 0, bottomInset);

This eliminates the two-writer race, requires ~60 lines in 1 file (vs. 150+ lines in 2 files for the PR), and relies on Android's natural inset dispatch to call OnApplyWindowInsets when IME state changes, avoiding the need for an explicit dismiss-path.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-safearea Issues/PRs that have to do with the SafeArea functionality community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

Status: Changes Requested

Development

Successfully merging this pull request may close these issues.

net 10 rc2 keyboard overlap android

9 participants