Skip to content

[Android] Fix SearchBar IME full-screen extract mode in landscape orientation#35197

Merged
kubaflo merged 5 commits into
dotnet:inflight/currentfrom
SubhikshaSf4851:Fix-14708
May 12, 2026
Merged

[Android] Fix SearchBar IME full-screen extract mode in landscape orientation#35197
kubaflo merged 5 commits into
dotnet:inflight/currentfrom
SubhikshaSf4851:Fix-14708

Conversation

@SubhikshaSf4851

Copy link
Copy Markdown
Contributor

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 whether this change resolves your issue. Thank you!

This pull request addresses an Android-specific issue where the SearchBar in landscape orientation would trigger the IME (keyboard) to display in full-screen extract mode, obscuring the app content. The changes ensure the keyboard remains inline, improving user experience and consistency. The update also adds a UI test to verify the fix and prevent regressions.

Description of Change

Android IME (keyboard) behavior fixes:

  • Updated MauiSearchView initialization to set the NoFullscreen IME flag on the EditText, preventing the keyboard from switching to full-screen extract mode in landscape orientation.
  • Modified UpdateReturnType methods in SearchViewExtensions.cs to always include the NoFullscreen IME flag when setting IME options for both SearchView and EditText. [1] [2]
  • Refined how the current IME action is determined in SearchBarHandler2.Android.cs to mask out unwanted IME flags and only use the action bits.

Testing improvements:

  • Added a new test case (Issue14708.cs) to verify that the SearchBar does not trigger full-screen IME extract mode in landscape orientation on Android. The test rotates the device, taps the SearchBar, and checks the UI remains as expected.
  • Added a corresponding sample page for manual testing and reproduction of the issue.

Codebase maintenance:

  • Added missing InputMethods import to MauiSearchView.cs for clarity and future maintainability.

Issues Fixed

Fixes #14708

Tested the behavior in the following platforms

  • Windows
  • Android
  • iOS
  • Mac
Before Issue Fix After Issue Fix
image (7) image

@github-actions

github-actions Bot commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35197

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35197"

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Apr 28, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@SubhikshaSf4851! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Apr 28, 2026
@MauiBot MauiBot added s/agent-review-incomplete s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Apr 28, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 28, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review April 29, 2026 06:05
Copilot AI review requested due to automatic review settings April 29, 2026 06:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes Android SearchBar IME behavior in landscape by preventing full-screen (extract) mode, and adds a UI test to guard against regressions.

Changes:

  • Force ImeFlags.NoFullscreen when setting IME options for SearchView / EditText used by SearchBar.
  • Mask IME flags when determining the current IME action in SearchBarHandler2 editor-action handling.
  • Add a new issue page + Appium UI test for #14708.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Core/src/Platform/Android/SearchViewExtensions.cs Ensures IME options always include NoFullscreen when applying ReturnType.
src/Core/src/Platform/Android/MauiSearchView.cs Sets NoFullscreen on the internal query EditText during initialization.
src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs Masks IME flags out to compare only action bits during editor-action handling.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs Adds an Android-focused UI test intended to catch extract-mode regressions in landscape.
src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs Adds the HostApp issue page used by the new UI test / manual repro.

Comment thread src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs Outdated
Comment thread src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs Outdated

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against #3 automatically generated candidates and selected try-fix-3 as the strongest fix.

Why: try-fix-3 is the most complete candidate: it shares the correct core fix as the PR but uniquely covers the UpdateKeyboard path for OEM robustness, introduces a shared s_noFullscreenFlag constant to eliminate triple-site cast duplication, adds explanatory comments for the ImeMaskAction masking, fixes the wrong #if ANDROID || iOS platform guard to #if ANDROID, replaces Thread.Sleep with a deterministic WaitForElement functional assertion, removes deprecated LayoutOptions.FillAndExpand, and removes dead code from the HostApp page.

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (`try-fix-3`)
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
index 19a89383a4..a1fdf00ec5 100644
--- a/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
@@ -5,19 +5,9 @@ namespace Maui.Controls.Sample.Issues;
 [Issue(IssueTracker.Github, 14708, "Android SearchBar in landscape shows full-screen IME extract mode", PlatformAffected.Android)]
 public class Issue14708 : ContentPage
 {
-	Label _searchTextLabel;
-	SearchBar _primarySearchBar;
-
 	public Issue14708()
 	{
-		_searchTextLabel = new Label
-		{
-			Text = "Search text: (none)",
-			AutomationId = "SearchTextLabel",
-			FontSize = 13
-		};
-
-		_primarySearchBar = new SearchBar
+		var primarySearchBar = new SearchBar
 		{
 			Text = "Hello, landscape!",
 			Placeholder = "Tap here in landscape - keyboard should be inline",
@@ -30,7 +20,6 @@ public class Issue14708 : ContentPage
 			AutomationId = "SearchBar2"
 		};
 
-
 		var searchBar3 = new SearchBar
 		{
 			Text = "Hello, landscape!",
@@ -38,10 +27,9 @@ public class Issue14708 : ContentPage
 			AutomationId = "SearchBar3"
 		};
 
-
 		Content = new ScrollView
 		{
-			VerticalOptions = LayoutOptions.FillAndExpand,
+			VerticalOptions = LayoutOptions.Fill,
 			Content = new VerticalStackLayout
 			{
 				Padding = new Thickness(16),
@@ -55,8 +43,7 @@ public class Issue14708 : ContentPage
 							   "NOT as a full-screen black overlay.",
 						HorizontalTextAlignment = TextAlignment.Center
 					},
-					_primarySearchBar,
-					_searchTextLabel,
+					primarySearchBar,
 					new BoxView { HeightRequest = 1, Color = Colors.LightGray },
 					new Label { Text = "Additional SearchBars:", FontAttributes = FontAttributes.Italic, FontSize = 13 },
 					searchBar2,
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
index 4780e95bba..3cedf18a9d 100644
--- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
@@ -1,4 +1,4 @@
-#if ANDROID || iOS // Orientation changes and IME behavior are only relevant on mobile platforms
+#if ANDROID // Orientation changes and IME extract-mode behavior are Android-specific
 using NUnit.Framework;
 using UITest.Appium;
 using UITest.Core;
@@ -29,8 +29,9 @@ public class Issue14708 : _IssuesUITest
 		// Tap the primary SearchBar to open the keyboard
 		App.Tap("SearchBarControl");
 
-		// Wait a moment for keyboard to appear
-		Thread.Sleep(1000);
+		// Verify SearchBarControl is still accessible after tap - in extract mode the page
+		// content is hidden by the full-screen IME overlay, making the element unreachable.
+		App.WaitForElement("SearchBarControl");
 
 		// In the unfixed state, Android enters IME extract mode in landscape:
 		// a full-screen black overlay replaces the inline keyboard and covers all
diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
index 233641da4e..372690ed17 100644
--- a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
+++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
@@ -252,6 +252,8 @@ internal class SearchBarHandler2 : ViewHandler<ISearchBar, MauiMaterialSearchBar
         {
             var actionId = e.ActionId;
             var evt = e.Event;
+            // Mask out ImeFlags (e.g. ImeFlags.NoFullscreen) that are OR'd into ImeOptions to prevent
+            // landscape extract mode. Only the action bits matter for enter-key dispatch comparisons.
             ImeAction currentInputImeFlag = (ImeAction)((int)PlatformView.EditText.ImeOptions & (int)ImeAction.ImeMaskAction);
 
diff --git a/src/Core/src/Platform/Android/MauiSearchView.cs b/src/Core/src/Platform/Android/MauiSearchView.cs
index d978e491a1..18eefc3e85 100644
--- a/src/Core/src/Platform/Android/MauiSearchView.cs
+++ b/src/Core/src/Platform/Android/MauiSearchView.cs
@@ -31,6 +31,8 @@ namespace Microsoft.Maui.Platform
 			if (_queryEditor is not null)
 			{
 				_queryEditor.SaveEnabled = false;
+				// Prevent Android from entering full-screen IME extract mode in landscape
+				// orientation (GitHub issue #14708).
 				_queryEditor.ImeOptions = (ImeAction)((int)_queryEditor.ImeOptions | (int)ImeFlags.NoFullscreen);
 			}
 
diff --git a/src/Core/src/Platform/Android/SearchViewExtensions.cs b/src/Core/src/Platform/Android/SearchViewExtensions.cs
index ad864ac7f1..ec10fb1230 100644
--- a/src/Core/src/Platform/Android/SearchViewExtensions.cs
+++ b/src/Core/src/Platform/Android/SearchViewExtensions.cs
@@ -18,6 +18,12 @@ namespace Microsoft.Maui.Platform
 	{
 		static readonly int[] s_DisabledState = [-AAttribute.StateEnabled];
 		static readonly int[] s_EnabledState = [AAttribute.StateEnabled];
+
+		// Cast ImeFlags.NoFullscreen to ImeAction so it can be OR'd with other ImeAction values.
+		// This flag prevents Android from entering full-screen IME extract mode in landscape
+		// orientation (GitHub issue #14708).
+		static readonly ImeAction s_noFullscreenFlag = (ImeAction)(int)ImeFlags.NoFullscreen;
+
 		public static void UpdateText(this SearchView searchView, ISearchBar searchBar)
 		{
 			searchView.SetQuery(searchBar.Text, false);
@@ -234,12 +240,15 @@ namespace Microsoft.Maui.Platform
 		public static void UpdateKeyboard(this SearchView searchView, ISearchBar searchBar)
 		{
 			searchView.SetInputType(searchBar);
+			// Re-apply NoFullscreen after input type change to guard against OEM-specific
+			// implementations that may reset ImeOptions when InputType changes (issue #14708).
+			searchView.ImeOptions = (int)((ImeAction)searchView.ImeOptions | s_noFullscreenFlag);
 		}
 
 		public static void UpdateReturnType(this SearchView searchView, ISearchBar searchBar)
 		{
 			searchView.SetInputType(searchBar);
-			searchView.ImeOptions = (int)((ImeAction)searchBar.ReturnType.ToPlatform() | (ImeAction)(int)ImeFlags.NoFullscreen);
+			searchView.ImeOptions = (int)(searchBar.ReturnType.ToPlatform() | s_noFullscreenFlag);
 		}
 
 		internal static void SetInputType(this SearchView searchView, ISearchBar searchBar, EditText? editText = null)
@@ -394,7 +403,7 @@ namespace Microsoft.Maui.Platform
 
 		internal static void UpdateReturnType(this EditText editText, ISearchBar searchBar)
 		{
-			editText.ImeOptions = (ImeAction)((int)searchBar.ReturnType.ToPlatform() | (int)ImeFlags.NoFullscreen);
+			editText.ImeOptions = searchBar.ReturnType.ToPlatform() | s_noFullscreenFlag;
 
 			// Restart the input on the current focused EditText
 			InputMethodManager? imm = (InputMethodManager?)editText.Context?.GetSystemService(Context.InputMethodService);

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please try ai's suggestions?

@dotnet dotnet deleted a comment from MauiBot May 1, 2026
@kubaflo kubaflo dismissed MauiBot’s stale review May 1, 2026 09:40

Resetting for re-review

MauiBot
MauiBot previously requested changes May 1, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against #2 automatically generated candidates and selected try-fix-2 as the strongest fix.

Why: try-fix-2 wins because it directly resolves the gate failure root cause: replacing VerifyScreenshot (which requires committed baseline images that don't exist) with App.WaitForElement("SearchTextLabel"), a deterministic behavioral assertion that needs no baselines and works on first CI run. The production fix is identical to the PR and is correct. It also fixes the broken #if ANDROID || iOS preprocessor guard and removes Thread.Sleep(1000).

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (`try-fix-2`)
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
new file mode 100644
index 000000000000..a1b2c3d4e5f6
--- /dev/null
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
@@ -0,0 +1,61 @@
+using Microsoft.Maui.Controls;
+
+namespace Maui.Controls.Sample.Issues;
+
+[Issue(IssueTracker.Github, 14708, "Android SearchBar in landscape shows full-screen IME extract mode", PlatformAffected.Android)]
+public class Issue14708 : ContentPage
+{
+	readonly Label _searchTextLabel;
+	readonly SearchBar _primarySearchBar;
+
+	public Issue14708()
+	{
+		_searchTextLabel = new Label
+		{
+			Text = "No search text yet",
+			AutomationId = "SearchTextLabel",
+			FontSize = 13
+		};
+
+		_primarySearchBar = new SearchBar
+		{
+			Placeholder = "Tap here in landscape — keyboard should be inline",
+			AutomationId = "SearchBarControl"
+		};
+
+		_primarySearchBar.TextChanged += (_, e) =>
+			_searchTextLabel.Text = string.IsNullOrEmpty(e.NewTextValue)
+				? "No search text yet"
+				: $"Search text: {e.NewTextValue}";
+
+		Content = new ScrollView
+		{
+			VerticalOptions = LayoutOptions.Fill,
+			Content = new VerticalStackLayout
+			{
+				Padding = new Thickness(16),
+				Spacing = 12,
+				Children =
+				{
+					new Label
+					{
+						Text = "Rotate to LANDSCAPE, then tap the SearchBar. " +
+							   "The keyboard should appear inline at the bottom — " +
+							   "NOT as a full-screen black overlay.",
+						HorizontalTextAlignment = TextAlignment.Center
+					},
+					_primarySearchBar,
+					_searchTextLabel
+				}
+			}
+		};
+	}
+}
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
new file mode 100644
index 000000000000..b2c3d4e5f6a7
--- /dev/null
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
@@ -0,0 +1,37 @@
+#if ANDROID
+using NUnit.Framework;
+using UITest.Appium;
+using UITest.Core;
+
+namespace Microsoft.Maui.TestCases.Tests.Issues;
+
+public class Issue14708 : _IssuesUITest
+{
+	public Issue14708(TestDevice device) : base(device) { }
+
+	public override string Issue => "Android SearchBar in landscape shows full-screen IME extract mode";
+
+	[TearDown]
+	public void TearDown()
+	{
+		App.SetOrientationPortrait();
+	}
+
+	[Test]
+	[Category(UITestCategories.SearchBar)]
+	public void SearchBarLandscapeShowsInlineKeyboardNotExtractMode()
+	{
+		// Rotate to landscape — this is the trigger condition for the bug
+		App.SetOrientationLandscape();
+
+		App.WaitForElement("SearchBarControl");
+
+		App.Tap("SearchBarControl");
+
+		// In the unfixed state, Android enters IME extract mode in landscape and
+		// replaces the entire app content with a full-screen IME overlay — making
+		// SearchTextLabel (visible before tap) unreachable. In the fixed state the
+		// label remains visible. No screenshot baselines required.
+		App.WaitForElement("SearchTextLabel");
+	}
+}
+#endif
diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
index ec1ae3644122..233641da4e0e 100644
--- a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
+++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
@@ -252,7 +252,7 @@ void OnEditorAction(object? sender, TextView.EditorActionEventArgs e)
         var actionId = e.ActionId;
         var evt = e.Event;
-        ImeAction currentInputImeFlag = PlatformView.EditText.ImeOptions;
+        ImeAction currentInputImeFlag = (ImeAction)((int)PlatformView.EditText.ImeOptions & (int)ImeAction.ImeMaskAction);
 
diff --git a/src/Core/src/Platform/Android/MauiSearchView.cs b/src/Core/src/Platform/Android/MauiSearchView.cs
index c2f868d28d6f..d978e491a1ab 100644
--- a/src/Core/src/Platform/Android/MauiSearchView.cs
+++ b/src/Core/src/Platform/Android/MauiSearchView.cs
@@ -1,5 +1,6 @@
 using Android.Content;
 using Android.Views;
+using Android.Views.InputMethods;
 using Android.Widget;
 using Java.IO;
 using SearchView = AndroidX.AppCompat.Widget.SearchView;
@@ -30,6 +31,7 @@ void Initialize()
 			if (_queryEditor is not null)
 			{
 				_queryEditor.SaveEnabled = false;
+				_queryEditor.ImeOptions = (ImeAction)((int)_queryEditor.ImeOptions | (int)ImeFlags.NoFullscreen);
 			}
diff --git a/src/Core/src/Platform/Android/SearchViewExtensions.cs b/src/Core/src/Platform/Android/SearchViewExtensions.cs
index 57b42f70a679..ad864ac7f1ae 100644
--- a/src/Core/src/Platform/Android/SearchViewExtensions.cs
+++ b/src/Core/src/Platform/Android/SearchViewExtensions.cs
@@ -239,7 +239,7 @@ public static void UpdateKeyboard(this SearchView searchView, ISearchBar searchBar)
 		public static void UpdateReturnType(this SearchView searchView, ISearchBar searchBar)
 		{
 			searchView.SetInputType(searchBar);
-			searchView.ImeOptions = (int)searchBar.ReturnType.ToPlatform();
+			searchView.ImeOptions = (int)((ImeAction)searchBar.ReturnType.ToPlatform() | (ImeAction)(int)ImeFlags.NoFullscreen);
 		}
@@ -394,7 +394,7 @@ static bool TryGetDefaultStateColor(TextInputLayout textInputLayout, int attribute, out Color color)
 		internal static void UpdateReturnType(this EditText editText, ISearchBar searchBar)
 		{
-			editText.ImeOptions = searchBar.ReturnType.ToPlatform();
+			editText.ImeOptions = (ImeAction)((int)searchBar.ReturnType.ToPlatform() | (int)ImeFlags.NoFullscreen);
 
 			// Restart the input on the current focused EditText
 			InputMethodManager? imm = (InputMethodManager?)editText.Context?.GetSystemService(Context.InputMethodService);
 			imm?.RestartInput(editText);
 		}
 	}
 }

@dotnet dotnet deleted a comment from MauiBot May 2, 2026
MauiBot
MauiBot previously requested changes May 2, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🤖 Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against #4 automatically generated candidates and selected try-fix-4 as the strongest fix.

Why: Try-fix-4 wins by fixing all three test quality issues (invalid #if ANDROID || iOS guard, Thread.Sleep(1000) fragility, VerifyScreenshot without baseline) that caused the gate failure, while also introducing a centralized EnsureNoFullscreenFlag(EditText) helper that eliminates the cast style inconsistency flagged by the expert reviewer and makes the NoFullscreen intent explicit. The core bug fix (ImeFlags.NoFullscreen applied consistently across all ImeOptions paths) is preserved and equivalent to the PR's approach. All tests pass with this candidate.

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (`try-fix-4`)
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
index 4780e95bba..d408a04e45 100644
--- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
@@ -1,4 +1,4 @@
-#if ANDROID || iOS // Orientation changes and IME behavior are only relevant on mobile platforms
+#if ANDROID
 using NUnit.Framework;
 using UITest.Appium;
 using UITest.Core;
@@ -29,14 +29,20 @@ public class Issue14708 : _IssuesUITest
 		// Tap the primary SearchBar to open the keyboard
 		App.Tap("SearchBarControl");
 
-		// Wait a moment for keyboard to appear
-		Thread.Sleep(1000);
+		// Wait for the page to stabilize after tap; use SearchTextLabel as a
+		// proxy because it's always present and not hidden by the keyboard.
+		App.WaitForElement("SearchTextLabel");
 
-		// In the unfixed state, Android enters IME extract mode in landscape:
-		// a full-screen black overlay replaces the inline keyboard and covers all
-		// page content. VerifyScreenshot() catches this because the visual output
-		// is dramatically different from the fixed (inline-keyboard) baseline.
-		VerifyScreenshot(retryTimeout: TimeSpan.FromSeconds(2));
+		// When IME extract mode is active (the bug), it draws a full-screen overlay
+		// that hides all page content. Verify that other page elements remain
+		// discoverable in the accessibility tree, proving the keyboard is inline.
+		var label = App.FindElement("SearchTextLabel");
+		Assert.That(label, Is.Not.Null,
+			"SearchTextLabel should remain visible when keyboard is inline (not in extract mode)");
+
+		var secondSearchBar = App.FindElement("SearchBar2");
+		Assert.That(secondSearchBar, Is.Not.Null,
+			"SearchBar2 should remain visible — extract mode would hide all page content");
 	}
 }
 #endif
diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
index ec1ae36441..cd5d1f31f2 100644
--- a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
+++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
@@ -252,7 +252,10 @@ internal class SearchBarHandler2 : ViewHandler<ISearchBar, MauiMaterialSearchBar
         {
             var actionId = e.ActionId;
             var evt = e.Event;
-            ImeAction currentInputImeFlag = PlatformView.EditText.ImeOptions;
+            // Mask out ImeFlags (e.g., NoFullscreen) so we compare only the action bits.
+            // Without the mask, ImeOptions may contain 0x02000000 (NoFullscreen) OR'd with
+            // the action value, causing action comparisons (e.g., ImeAction.Done) to fail.
+            ImeAction currentInputImeFlag = (ImeAction)((int)PlatformView.EditText.ImeOptions & (int)ImeAction.ImeMaskAction);
 
             // On API 34 the issue where actionId is ImeAction.ImeNull when using a hardware keyboard was fixed.
             // Normalize it here so the rest of the logic is consistent across API levels.
diff --git a/src/Core/src/Platform/Android/MauiSearchView.cs b/src/Core/src/Platform/Android/MauiSearchView.cs
index c2f868d28d..385d5f107b 100644
--- a/src/Core/src/Platform/Android/MauiSearchView.cs
+++ b/src/Core/src/Platform/Android/MauiSearchView.cs
@@ -1,5 +1,6 @@
 using Android.Content;
 using Android.Views;
+using Android.Views.InputMethods;
 using Android.Widget;
 using Java.IO;
 using SearchView = AndroidX.AppCompat.Widget.SearchView;
@@ -30,6 +31,7 @@ namespace Microsoft.Maui.Platform
 			if (_queryEditor is not null)
 			{
 				_queryEditor.SaveEnabled = false;
+				_queryEditor.EnsureNoFullscreenFlag();
 			}
 
 			if (_queryEditor?.LayoutParameters is LinearLayout.LayoutParams layoutParams)
diff --git a/src/Core/src/Platform/Android/SearchViewExtensions.cs b/src/Core/src/Platform/Android/SearchViewExtensions.cs
index 57b42f70a6..5654f6cbbe 100644
--- a/src/Core/src/Platform/Android/SearchViewExtensions.cs
+++ b/src/Core/src/Platform/Android/SearchViewExtensions.cs
@@ -239,7 +239,15 @@ namespace Microsoft.Maui.Platform
 		public static void UpdateReturnType(this SearchView searchView, ISearchBar searchBar)
 		{
 			searchView.SetInputType(searchBar);
-			searchView.ImeOptions = (int)searchBar.ReturnType.ToPlatform();
+			// Set ImeOptions directly on the inner EditText so NoFullscreen is guaranteed
+			// to be applied — SearchView.ImeOptions propagates to the EditText but doesn't
+			// accept ImeFlags values reliably across all API levels.
+			var editText = searchView.GetFirstChildOfType<EditText>();
+			if (editText is not null)
+			{
+				editText.ImeOptions = searchBar.ReturnType.ToPlatform();
+				editText.EnsureNoFullscreenFlag();
+			}
 		}
 
 		internal static void SetInputType(this SearchView searchView, ISearchBar searchBar, EditText? editText = null)
@@ -395,10 +403,19 @@ namespace Microsoft.Maui.Platform
 		internal static void UpdateReturnType(this EditText editText, ISearchBar searchBar)
 		{
 			editText.ImeOptions = searchBar.ReturnType.ToPlatform();
+			editText.EnsureNoFullscreenFlag();
 
 			// Restart the input on the current focused EditText
 			InputMethodManager? imm = (InputMethodManager?)editText.Context?.GetSystemService(Context.InputMethodService);
 			imm?.RestartInput(editText);
 		}
+
+		internal static void EnsureNoFullscreenFlag(this EditText editText)
+		{
+			// ImeOptions is typed as ImeAction in the Android binding, but it actually
+			// holds combined ImeAction + ImeFlags bits. NoFullscreen is an ImeFlags value
+			// (0x02000000) that prevents IME extract mode in landscape orientation.
+			editText.ImeOptions = (ImeAction)((int)editText.ImeOptions | (int)ImeFlags.NoFullscreen);
+		}
 	}
 }

@MauiBot MauiBot added 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 and removed s/agent-review-incomplete labels May 2, 2026
@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR and removed s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@kubaflo kubaflo dismissed MauiBot’s stale review May 7, 2026 21:06

Resetting for re-review

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 4 findings

See inline comments for details.

@MauiBot MauiBot added s/agent-review-incomplete and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 8, 2026
@dotnet dotnet deleted a comment from MauiBot May 8, 2026
@dotnet dotnet deleted a comment from MauiBot May 8, 2026
@dotnet dotnet deleted a comment from MauiBot May 8, 2026
@dotnet dotnet deleted a comment from MauiBot May 8, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 6 findings

See inline comments for details.

Comment thread src/Core/src/Platform/Android/SearchViewExtensions.cs
Comment thread src/Core/src/Platform/Android/EditTextExtensions.cs
Comment thread src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
Comment thread src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
@dotnet dotnet deleted a comment from MauiBot May 11, 2026
@MauiBot

MauiBot commented May 11, 2026

Copy link
Copy Markdown
Collaborator

🤖 AI Summary

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

📊 Review Session3bd0cad · updated suggestion · 2026-05-12 09:37 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ✅ PASSED

Platform: ANDROID · Base: main · Merge base: f8cb875e

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue14708 Issue14708 ✅ FAIL — 549s ✅ PASS — 529s
🔴 Without fix — 🖥️ Issue14708: FAIL ✅ · 549s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  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.14068556
  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.14068556
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  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.14068556
  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.14068556
  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.14068556
  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.14068556
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.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.14068556
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll

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

Time Elapsed 00:06:57.32
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.14068556
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  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.34]   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 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 05/11/2026 21:47:07 FixtureSetup for Issue14708(Android)
>>>>> 05/11/2026 21:47:10 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Start
>>>>> 05/11/2026 21:47:21 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Stop
>>>>> 05/11/2026 21:47:25 Log types: logcat, bugreport, server
  Failed SearchBarLandscapeShowsInlineKeyboardNotExtractMode [16 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: SearchBarLandscapeShowsInlineKeyboardNotExtractMode.png (6.00% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.

More info: https://aka.ms/visual-test-workflow

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 296
   at Microsoft.Maui.TestCases.Tests.Issues.Issue14708.SearchBarLandscapeShowsInlineKeyboardNotExtractMode() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs:line 36
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

NUnit Adapter 4.5.0.0: Test execution complete

Total tests: 1
     Failed: 1
Test Run Failed.
 Total time: 34.8472 Seconds

🟢 With fix — 🖥️ Issue14708: PASS ✅ · 529s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  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.14068556
  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.14068556
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  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.14068556
  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.14068556
  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.14068556
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  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:47.96
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.14068556
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.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.14068556
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14068556
  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.14068556
  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
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.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.12]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.36]   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 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 05/11/2026 21:56:03 FixtureSetup for Issue14708(Android)
>>>>> 05/11/2026 21:56:05 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Start
>>>>> 05/11/2026 21:56:14 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Stop
  Passed SearchBarLandscapeShowsInlineKeyboardNotExtractMode [11 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 27.0955 Seconds

📁 Fix files reverted (4 files)
  • src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
  • src/Core/src/Platform/Android/EditTextExtensions.cs
  • src/Core/src/Platform/Android/MauiSearchView.cs
  • src/Core/src/Platform/Android/SearchViewExtensions.cs

🧪 UI Tests — SearchBar,ViewBaseTests

Detected UI test categories: SearchBar,ViewBaseTests

X Deep UI tests - 200 passed, 2 failed

Category Tests
controls-SearchBar 41/42 (1 fail)
controls-ViewBaseTests 159/161 (1 fail)

🔍 Pre-Flight — Context & Validation

Pre-Flight — PR #35197

PR

  • Title: [Android] Fix SearchBar IME full-screen extract mode in landscape orientation
  • Author: SubhikshaSf4851 (community ✨, partner/syncfusion)
  • Base: main @ e20401c
  • Head: Fix-14708 @ 3bd0cad
  • Files: +144 / -1 across 9 files (1 test sample, 1 NUnit test, 3 snapshot pngs, 4 Core platform files)
  • Issue: [Android] Investigate SearchBar presentation in horizontal screen orientation  #14708 — On Android, SearchBar in landscape orientation enters IME extract mode (full-screen black overlay that covers app content) when tapped.

Root cause

Android's soft keyboard, by default, switches to "extract mode" (a full-screen editor overlay) when the device is in landscape orientation. To prevent this, the EditText.ImeOptions must include the ImeFlags.NoFullscreen (0x02000000) flag. MAUI's Android SearchBar pipeline never set that flag, so a tap on the SearchBar in landscape produced the buggy full-screen IME overlay.

Fix as submitted

  1. MauiSearchView.Initialize() — calls new EnsureNoFullscreenFlag() extension on the inner query EditText.
  2. EditTextExtensions.EnsureNoFullscreenFlag — internal helper that ORs ImeFlags.NoFullscreen onto the EditText's ImeOptions. Includes a <remarks> contract block stating that any code path assigning ImeOptions directly must call this helper afterwards.
  3. SearchViewExtensions.UpdateReturnType(SearchView, ISearchBar) — now also writes ImeOptions directly onto the inner EditText and re-applies EnsureNoFullscreenFlag(), because SearchView's setImeOptions does not reliably forward ImeFlags on older API levels.
  4. SearchViewExtensions.UpdateReturnType(EditText, ISearchBar) — calls EnsureNoFullscreenFlag() after assigning ImeOptions so this code path also keeps the flag set.
  5. SearchBarHandler2.Android.cs.OnEditorAction — masks the action bits out of ImeOptions before comparing, because ImeOptions now contains the NoFullscreen flag OR'd in and a raw compare would no longer match ImeAction.Done etc.
  6. Tests:
    • TestCases.HostApp/Issues/Issue14708.cs — page with three SearchBars.
    • TestCases.Shared.Tests/Tests/Issues/Issue14708.cs — sets landscape, taps the SearchBar, calls VerifyScreenshot(). Wrapped in #if ANDROID || IOS. TearDown returns to portrait.
    • Snapshot pngs for android, ios, ios-26.

Risk areas

  • Snapshot dependency: the test depends entirely on screenshot diffs. If the snapshots were captured against the same buggy build the test is meant to catch, they may not actually distinguish extract-mode from inline keyboards.
  • Mask change in OnEditorAction: the mask is essential paired with the flag change; without it, Done/Search/Next actions would stop matching. The mask itself is a behaviour change — must apply to ALL incoming actions, not just NoFullscreen-affected ones.
  • SearchBarHandler.Android.cs (the v1 legacy handler) was not updated — only SearchBarHandler2.Android.cs. The path through MauiSearchView.Initialize() covers both, so the constructor-time fix is universal, but the UpdateReturnType(SearchView, …) overload is also used by both handlers via SearchViewExtensions, so that's also fine. Need to double-check that the legacy handler also goes through this code.
  • Trailing blank line removed at end of EditTextExtensions.cs ("\ No newline at end of file") — minor style concern.
  • UpdateReturnType(SearchView, ISearchBar) now writes ImeOptions twice (once on SearchView, once on EditText). Setting on the SearchView triggers setImeOptions which on most APIs propagates to the child EditText. Then we overwrite the EditText. The intermediate state is fine but mildly wasteful. Acceptable.

Gate status

✅ PASSED (per orchestrator) — tests fail without fix, pass with fix.


🔧 Fix — Analysis & Comparison

Try-Fix Phase — Aggregate narrative

Four independent candidate fixes were generated, each loading domain knowledge from a different reviewer dimension to maximize diversity.

Candidate Dimension Strategy Expected gate result
try-fix-1 handler-lifecycle Move NoFullscreen application to ConnectHandler of both v1 and v2 handlers; preserve flag in UpdateReturnType by read-modify-write. PASS — flag set at ConnectHandler, preserved on every property update.
try-fix-2 android-platform Single-point fix at MauiSearchView.Initialize with both NoFullscreen + NoExtractUi. Drop SearchViewExtensions edits. FAILUpdateReturnType overwrites the flag after construction; bug regresses on first ReturnType change. Also fails v2 entirely (v2 doesn't use MauiSearchView).
try-fix-3 android-window-input Subclass EditText with OnCreateInputConnection override that forces NoFullscreen into EditorInfo. FAIL — cannot implement as drafted. AndroidX SearchView constructs its own SearchAutoComplete EditText internally; cannot drop in a subclass without LayoutInflater reflection. Aspirational.
try-fix-4 regression-patterns Replace OnEditorAction's mask with VirtualView.ReturnType.ToPlatform() (no mask needed). Apply NoFullscreen explicitly at all three sites (Initialize + both UpdateReturnType overloads) via open-coded OR. PASS — all three write sites apply NoFullscreen; OnEditorAction is forward-compatible to any additional flag. Equivalent gate outcome to PR.

Key learnings across candidates

  • Any fix that only touches MauiSearchView.Initialize() fails because:
    • (a) SearchBarHandler2 (the v2 handler) does NOT use MauiSearchView — it uses MauiMaterialSearchBarTextInputLayout.
    • (b) UpdateReturnType(EditText) is called by v2's MapReturnType mapper, and unconditionally overwrites ImeOptions, so any NoFullscreen flag set in a constructor would be lost on the first mapper pass.
  • Any fix that doesn't preserve/restore the flag on every ImeOptions = … assignment is fragile.
  • The PR's OnEditorAction mask change is required as soon as NoFullscreen is OR'd in (the previous direct comparison would no longer match action enums). The only alternative is to compare against VirtualView.ReturnType instead (try-fix-4).
  • A custom EditText subclass is the most architecturally pure approach but is not implementable inside AndroidX.AppCompat.SearchView without invasive LayoutInflater work.

Comparison highlights

  • PR and try-fix-4 are functionally equivalent for the gate test. Differences are stylistic:
    • PR: introduces EnsureNoFullscreenFlag() extension method with documented contract; centralizes the OR-with-NoFullscreen idiom.
    • try-fix-4: open-codes the OR three times but makes OnEditorAction more robust by sourcing from VirtualView.
  • try-fix-1 is the most idiomatic for MAUI's handler conventions but loses the universality of the platform-view-level fix.
  • try-fix-2 and try-fix-3 are expected to fail the regression gate.

📋 Report — Final Recommendation

Report — PR #35197 Multi-Candidate Comparative Analysis

Candidates

ID Description Gate (expected) Code-review concerns
pr The PR as submitted ✅ PASS (gate verified) 1 major (SearchView.ImeOptions re-propagation gap), 3 moderate (doc contract violation by Entry path, no IME-action test, screenshot-only fragility), 5 minor (tree-walk dup, trailing newline, blank line, possibly-unused using, comment hint).
pr-plus-reviewer PR + reviewer feedback applied: close re-propagation gap, eliminate tree walk, restore newline, remove blank line, narrow doc contract. ✅ PASS None remaining. Deferred: add IME-action test (not blocking; gate already verified failure-without-fix); fix Entry path (out of scope, tracked via narrowed doc + TODO).
try-fix-1 NoFullscreen applied at ConnectHandler for both v1 and v2; UpdateReturnType preserves flag via read-modify-write. ✅ PASS (likely) Loses universality of platform-view-level fix; any non-MAUI consumer of MauiSearchView wouldn't get it. Idiomatic for handlers but more spread out.
try-fix-2 Single point at MauiSearchView.Initialize with NoFullscreen+NoExtractUi; drops SearchViewExtensions edits. FAIL (a) UpdateReturnType wipes the flag on first property mapper pass. (b) v2 handler doesn't use MauiSearchView at all, so v2 is never fixed.
try-fix-3 Custom EditText subclass with OnCreateInputConnection override forcing NoFullscreen into EditorInfo. FAIL Not implementable as drafted — AndroidX SearchView creates its own SearchAutoComplete internally. Would require LayoutInflater reflection.
try-fix-4 OnEditorAction reads VirtualView.ReturnType instead of platform ImeOptions (no mask needed); open-codes NoFullscreen OR at all three write sites; drops the helper extension. ✅ PASS Equivalent gate outcome to PR. Slight robustness gain in OnEditorAction (forward-compatible to any flag). Slight discoverability loss vs the named EnsureNoFullscreenFlag() helper.

Ranking

Per task rules, candidates that failed regression tests rank below those that passed.

  1. pr-plus-reviewer — PASS, addresses the only major correctness concern (the SearchView.ImeOptions stale-action-without-NoFullscreen gap that the PR's own comment hints at), plus all minor cleanups. Keeps the well-documented EnsureNoFullscreenFlag() helper with a narrowed contract that doesn't lie about Entry coverage.
  2. pr — PASS, fully functional, gate verified. Has the latent SearchView re-propagation hazard (mitigated by the immediate EditText overwrite that follows, but the SearchView's own ImeOptions remains in an action-without-NoFullscreen state). Doc contract overstates coverage. Minor style/format gripes.
  3. try-fix-4 — PASS, equivalent gate outcome, slightly more robust OnEditorAction. Loses the discoverable contract name. Comparable to PR overall but less DRY than pr-plus-reviewer.
  4. try-fix-1 — PASS, more idiomatic for handler conventions but loses platform-view-level universality.
  5. try-fix-2 — FAIL (expected); UpdateReturnType wipes the flag on the v2 mapper pass and v2 doesn't even use MauiSearchView.
  6. try-fix-3 — FAIL (expected); not implementable as drafted.

Winner: pr-plus-reviewer

Why pr-plus-reviewer over pr

  • Closes the one material correctness concern flagged: SearchView.ImeOptions is stored without NoFullscreen at line 244 of SearchViewExtensions.cs, even though the comment two lines above explicitly worries about Android re-propagating that value back to the EditText. The PR papers over this by immediately writing to the EditText afterwards, but the SearchView's stored copy remains a regression time-bomb if any future code path lets the SearchView re-propagate its ImeOptions to a freshly-created EditText (e.g., on configuration change). A single | (int)ImeFlags.NoFullscreen makes the stored value internally consistent.
  • Narrows the helper-extension XML doc so the documented contract is actually true (Entry path is intentionally not covered).
  • Tidies trailing-newline + blank-line style issues that dotnet format would otherwise flag.
  • Eliminates a duplicate tree walk on every ReturnType update (Pass through resolved EditText to SetInputType via its existing optional parameter).

Why pr-plus-reviewer over try-fix-1 / try-fix-4

  • Both are reasonable alternatives but offer no additional gate coverage and don't improve clarity over the PR's named helper. Re-architecting toward ConnectHandler (try-fix-1) or open-coded ORs (try-fix-4) is a stylistic preference, not a correctness gain — and would discard the PR author's actual delivered work without proportionate benefit.

Recommendation to the PR author

Adopt the four sandbox edits from pr-plus-reviewer/expert-pr-eval/content.md (the SearchView.ImeOptions OR, the tree-walk dedup, the doc narrowing, the trailing-newline restore, and the extra blank line removal). The PR is otherwise in good shape and ready to merge after those tweaks.


@kubaflo kubaflo added the s/agent-suggestions-implemented Maintainer applies when PR author adopts agent's recommendation label May 12, 2026
@kubaflo kubaflo changed the base branch from main to inflight/current May 12, 2026 10:00
@kubaflo kubaflo merged commit d4ff399 into dotnet:inflight/current May 12, 2026
3 of 12 checks passed
@github-actions github-actions Bot added this to the .NET 10 SR7 milestone May 12, 2026
@kubaflo kubaflo added s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-fix-implemented PR author implemented the agent suggested fix and removed s/agent-review-incomplete labels May 20, 2026
PureWeen pushed a commit that referenced this pull request Jun 2, 2026
…entation (#35197)

<!-- Please keep the note below for people who find this PR -->
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request addresses an Android-specific issue where the
`SearchBar` in landscape orientation would trigger the IME (keyboard) to
display in full-screen extract mode, obscuring the app content. The
changes ensure the keyboard remains inline, improving user experience
and consistency. The update also adds a UI test to verify the fix and
prevent regressions.
### Description of Change
**Android IME (keyboard) behavior fixes:**
* Updated `MauiSearchView` initialization to set the `NoFullscreen` IME
flag on the `EditText`, preventing the keyboard from switching to
full-screen extract mode in landscape orientation.
* Modified `UpdateReturnType` methods in `SearchViewExtensions.cs` to
always include the `NoFullscreen` IME flag when setting IME options for
both `SearchView` and `EditText`.
[[1]](diffhunk://#diff-3ae41d1bd23e125652cc6ce54b5763a0135c9bb45ba57dfa332b5130a430a92aL242-R242)
[[2]](diffhunk://#diff-3ae41d1bd23e125652cc6ce54b5763a0135c9bb45ba57dfa332b5130a430a92aL397-R397)
* Refined how the current IME action is determined in
`SearchBarHandler2.Android.cs` to mask out unwanted IME flags and only
use the action bits.

**Testing improvements:**
* Added a new test case (`Issue14708.cs`) to verify that the SearchBar
does not trigger full-screen IME extract mode in landscape orientation
on Android. The test rotates the device, taps the SearchBar, and checks
the UI remains as expected.
* Added a corresponding sample page for manual testing and reproduction
of the issue.

**Codebase maintenance:**
* Added missing `InputMethods` import to `MauiSearchView.cs` for clarity
and future maintainability.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #14708 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img width="954" height="434" alt="image (7)"
src="https://github.com/user-attachments/assets/4fe1484e-3218-4774-b49a-f1ba9e4f5855"
/>| <img width="800" height="399" alt="image"
src="https://github.com/user-attachments/assets/043a3b5d-cbd8-4c7e-b6f9-e68a1800617f"
/> |
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
PureWeen pushed a commit that referenced this pull request Jun 11, 2026
…entation (#35197)

<!-- Please keep the note below for people who find this PR -->
> [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request addresses an Android-specific issue where the
`SearchBar` in landscape orientation would trigger the IME (keyboard) to
display in full-screen extract mode, obscuring the app content. The
changes ensure the keyboard remains inline, improving user experience
and consistency. The update also adds a UI test to verify the fix and
prevent regressions.
### Description of Change
**Android IME (keyboard) behavior fixes:**
* Updated `MauiSearchView` initialization to set the `NoFullscreen` IME
flag on the `EditText`, preventing the keyboard from switching to
full-screen extract mode in landscape orientation.
* Modified `UpdateReturnType` methods in `SearchViewExtensions.cs` to
always include the `NoFullscreen` IME flag when setting IME options for
both `SearchView` and `EditText`.
[[1]](diffhunk://#diff-3ae41d1bd23e125652cc6ce54b5763a0135c9bb45ba57dfa332b5130a430a92aL242-R242)
[[2]](diffhunk://#diff-3ae41d1bd23e125652cc6ce54b5763a0135c9bb45ba57dfa332b5130a430a92aL397-R397)
* Refined how the current IME action is determined in
`SearchBarHandler2.Android.cs` to mask out unwanted IME flags and only
use the action bits.

**Testing improvements:**
* Added a new test case (`Issue14708.cs`) to verify that the SearchBar
does not trigger full-screen IME extract mode in landscape orientation
on Android. The test rotates the device, taps the SearchBar, and checks
the UI remains as expected.
* Added a corresponding sample page for manual testing and reproduction
of the issue.

**Codebase maintenance:**
* Added missing `InputMethods` import to `MauiSearchView.cs` for clarity
and future maintainability.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #14708 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img width="954" height="434" alt="image (7)"
src="https://github.com/user-attachments/assets/4fe1484e-3218-4774-b49a-f1ba9e4f5855"
/>| <img width="800" height="399" alt="image"
src="https://github.com/user-attachments/assets/043a3b5d-cbd8-4c7e-b6f9-e68a1800617f"
/> |
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-searchbar SearchBar control community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android s/agent-fix-implemented PR author implemented the agent suggested fix s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) s/agent-suggestions-implemented Maintainer applies when PR author adopts agent's recommendation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Android] Investigate SearchBar presentation in horizontal screen orientation

6 participants