Skip to content

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

Open
SubhikshaSf4851 wants to merge 3 commits intodotnet:mainfrom
SubhikshaSf4851:Fix-14708
Open

[Android] Fix SearchBar IME full-screen extract mode in landscape orientation#35197
SubhikshaSf4851 wants to merge 3 commits intodotnet:mainfrom
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
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

🚀 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 AI agent could not complete all phases (blocker, timeout, error) 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
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

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
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

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);

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 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
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

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
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

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 AI agent could not complete all phases (blocker, timeout, error) labels May 2, 2026
Comment thread src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs Outdated
Comment thread src/Core/src/Platform/Android/SearchViewExtensions.cs Outdated
@SubhikshaSf4851
Copy link
Copy Markdown
Contributor Author

@kubaflo I have updated the changes

@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
@dotnet dotnet deleted a comment from MauiBot May 7, 2026
MauiBot
MauiBot previously requested changes May 7, 2026
Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

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 (gpt-5.3-codex) wins: it is the most minimal verified fix (3 lines across 3 files), directly addresses the code review's key warning by including NoFullscreen in searchView.ImeOptions itself, and also fixes the spurious #if ANDROID || IOS test guard. Unlike the PR's multi-call-site EnsureNoFullscreenFlag approach, it relies on AppCompat's built-in SearchView→EditText ImeOptions propagation, eliminating the fragile ordering dependency. Gate failure for the PR was a snapshot baseline mismatch (infrastructure), not a code correctness issue.

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.Shared.Tests/Tests/Issues/Issue14708.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
index 7f02d242f5..ce909ee5f8 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;
diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
index ec1ae36441..233641da4e 100644
--- a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
+++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
@@ -252,7 +252,7 @@ internal class SearchBarHandler2 : ViewHandler<ISearchBar, MauiMaterialSearchBar
         {
             var actionId = e.ActionId;
             var evt = e.Event;
-            ImeAction currentInputImeFlag = PlatformView.EditText.ImeOptions;
+            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/SearchViewExtensions.cs b/src/Core/src/Platform/Android/SearchViewExtensions.cs
index 57b42f70a6..aaa1d16bbd 100644
--- a/src/Core/src/Platform/Android/SearchViewExtensions.cs
+++ b/src/Core/src/Platform/Android/SearchViewExtensions.cs
@@ -239,7 +239,7 @@ namespace Microsoft.Maui.Platform
 		public static void UpdateReturnType(this SearchView searchView, ISearchBar searchBar)
 		{
 			searchView.SetInputType(searchBar);
-			searchView.ImeOptions = (int)searchBar.ReturnType.ToPlatform();
+			searchView.ImeOptions = (int)searchBar.ReturnType.ToPlatform() | (int)ImeFlags.NoFullscreen;
 		}
 
 		internal static void SetInputType(this SearchView searchView, ISearchBar searchBar, EditText? editText = null)

@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 AI agent could not complete all phases (blocker, timeout, error) 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

Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

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 AI agent could not complete all phases (blocker, timeout, error) 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
@kubaflo
Copy link
Copy Markdown
Contributor

kubaflo commented May 8, 2026

🤖 AI Summary

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

📊 Review Session0afc83b · committed the suggestion · 2026-05-08 09:40 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ✅ PASSED

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

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue14708 Issue14708 ✅ FAIL — 568s ✅ PASS — 529s
🔴 Without fix — 🖥️ Issue14708: FAIL ✅ · 568s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  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.14042760
  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.14042760
  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.14042760
  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.14042760
  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.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.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.14042760
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.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.14042760
  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.14042760
  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.14042760
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.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.14042760
  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.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  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.14042760
  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:07:01.76
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.14042760
  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.14042760
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  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.14042760
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.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.11]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.31]   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/07/2026 22:10:39 FixtureSetup for Issue14708(Android)
>>>>> 05/07/2026 22:10:41 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Start
>>>>> 05/07/2026 22:10:53 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Stop
>>>>> 05/07/2026 22:10:57 Log types: logcat, bugreport, server
  Failed SearchBarLandscapeShowsInlineKeyboardNotExtractMode [16 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: SearchBarLandscapeShowsInlineKeyboardNotExtractMode.png (6.02% 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

Test Run Failed.
Total tests: 1
     Failed: 1
 Total time: 32.5359 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.14042760
  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.14042760
  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.14042760
  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.14042760
  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.14042760
  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.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  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
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.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.14042760
  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.14042760
  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.14042760
  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.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  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.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  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
  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

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

Time Elapsed 00:06:48.64
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.14042760
  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.14042760
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14042760
  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.14042760
  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.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.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
  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.11]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.31]   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/07/2026 22:19:33 FixtureSetup for Issue14708(Android)
>>>>> 05/07/2026 22:19:36 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Start
>>>>> 05/07/2026 22:19:44 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: 26.6090 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 — Category Detection

Detected UI test categories: SearchBar,ViewBaseTests

🧪 UI Test Execution Results

FAILED — 1 passed, 1 failed, 0 skipped (platform: android)

Category Result Duration Notes
SearchBar ❌ FAILED 1685.9s exit code 1
ViewBaseTests ✅ PASSED 863.2s

Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.


🔍 Regression Cross-Reference

🔍 Regression Cross-Reference

🟢 No regression risks detected. No labeled bug-fix PRs in the last 6 months touched the modified files.


🔍 Pre-Flight — Context & Validation

Pre-Flight — PR #35197

Issue

  • [Android] Investigate SearchBar presentation in horizontal screen orientation  #14708[Android] Investigate SearchBar presentation in horizontal screen orientation
  • Symptom: Tapping the SearchBar in landscape orientation pops the IME into Android's full-screen "extract" mode (a giant black overlay with the SearchBar text field stretched across the whole screen and a default Android SEARCH button), covering the rest of the page. Typing while already focused does NOT trigger it; only fresh taps do. Affects platform: Android.
  • Root cause: Android's IME enters extract mode by default in landscape unless the focused EditText has the ImeFlags.NoFullscreen (0x02000000) flag OR'd into ImeOptions. MAUI's SearchBar Android handler never sets that flag on the inner EditText of the platform SearchView.

PR Summary

  • Author: SubhikshaSf4851 (community / partner: Syncfusion)
  • Base: main · Head: Fix-14708
  • Title: [Android] Fix SearchBar IME full-screen extract mode in landscape orientation
  • Files changed (production):
    • src/Core/src/Platform/Android/EditTextExtensions.cs — adds internal extension EnsureNoFullscreenFlag(this EditText) that ORs ImeFlags.NoFullscreen into ImeOptions.
    • src/Core/src/Platform/Android/MauiSearchView.cs — calls EnsureNoFullscreenFlag() on the inner _queryEditor during construction.
    • src/Core/src/Platform/Android/SearchViewExtensions.csUpdateReturnType(SearchView) now also writes ImeOptions directly on the inner EditText and re-applies EnsureNoFullscreenFlag(). UpdateReturnType(EditText) re-applies EnsureNoFullscreenFlag() after writing ImeOptions.
    • src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs — masks ImeOptions with ImeAction.ImeMaskAction when computing currentInputImeFlag so the action comparison in OnEditorAction still works once NoFullscreen is OR'd in.
  • Files changed (tests): new HostApp page Issue14708.cs, new shared UITest Issue14708.cs with SearchBarLandscapeShowsInlineKeyboardNotExtractMode (uses SetOrientationLandscape + VerifyScreenshot), 3 baseline screenshots (android, ios, ios-26).

Classification

Area Category Notes
EditTextExtensions.cs Platform/Android New internal helper EnsureNoFullscreenFlag. File missing trailing newline (pre-existing).
MauiSearchView.cs Platform/Android Single call site addition + new using Android.Views.InputMethods;.
SearchViewExtensions.cs Platform/Android Both UpdateReturnType overloads re-apply NoFullscreen. The SearchView overload now also writes ImeOptions directly on inner EditText with the comment that SearchView.ImeOptions "doesn't reliably accept ImeFlags on all API levels".
SearchBarHandler2.Android.cs Handler (material3, internal) Defensive mask only. NoFullscreen is not applied via this handler — see ⚠️ below.
Issue14708 HostApp + UITest Tests Screenshot-based; rotates to landscape, taps SearchBar, asserts inline keyboard via VerifyScreenshot.

Code Review Findings (advisory hints for try-fix)

❌ Errors / risks

  1. SearchBarHandler2.Android.cs — only the mask is added; NoFullscreen is never set.
    • SearchBarHandler2 uses MauiMaterialSearchBarTextInputLayout whose inner MauiMaterialSearchBarTextInputEditText is not a SearchView and never goes through MauiSearchView or SearchViewExtensions.UpdateReturnType. So in the Material 3 SearchBar (currently internal, slated to be public in net11), the bug is NOT fixed — only the broken OnEditorAction comparison logic that would break if anyone added the flag elsewhere.
    • Net effect today: the mask change is harmless but unnecessary, because nothing in this handler currently sets NoFullscreen. The handler still produces the buggy fullscreen-extract behaviour when made public.
  2. EditTextExtensions.cs is missing the trailing newline at EOF (pre-existing in the repo, but the diff worsens it because the new method is the last code in the file). Some diff/format tooling will flag this; dotnet format may rewrite the file.

⚠️ Warnings

  1. Force-on policy. EnsureNoFullscreenFlag is now applied unconditionally on every MauiSearchView construction and every UpdateReturnType call. This is fine for the SearchBar use-case (no public surface controls extract mode for SearchBar) but the helper is placed on the general EditTextExtensions and may be tempting to call from Entry/Editor paths where users could legitimately rely on extract mode.
  2. Two writes of editText.ImeOptions per UpdateReturnType call. SearchViewExtensions.UpdateReturnType(SearchView) first calls searchView.SetInputType(searchBar) (which can write ImeOptions on the inner EditText via EditTextExtensions.SetInputType), then sets searchView.ImeOptions, then writes the inner editText.ImeOptions again, then OR's NoFullscreen. The duplication is intentional (the comment says SearchView.ImeOptions doesn't reliably propagate), but if SetInputType ever moves the order around the flag could be lost.
  3. UpdateReturnType does not call RestartInput on the SearchView path. The standalone EditText overload restarts the IMM input so the keyboard reflects the new return key. The SearchView path does not — meaning in the very rare case an open keyboard is already showing on the SearchBar at the moment ReturnType changes, the keyboard won't re-render. Pre-existing behaviour, untouched by this PR.

💡 Suggestions

  1. The EnsureNoFullscreenFlag helper is SearchBar-specific in spirit; it could live next to MauiSearchView (or be a private static method) instead of being added to the broad EditTextExtensions surface.
  2. Consider applying NoFullscreen once at _queryEditor creation time (in MauiSearchView ctor) and not bothering to re-apply on every UpdateReturnType. ImeOptions is sticky on the EditText; it only needs to be re-OR'd if some other code path overwrites ImeOptions wholesale. The PR currently re-applies in 3 places out of caution.

Failure-mode probes (relevant to try-fix candidates)

  • Custom ReturnType (Send/Done/Go) — does the masked comparison in SearchBarHandler2.OnEditorAction still raise SearchButtonPressed? Yes, because (ImeOptions & ImeMaskAction) == ImeAction.Done once the NoFullscreen high bit is masked out. The mask is correct.
  • Hardware keyboardactionId == ImeAction.ImeNull path uses currentInputImeFlag; mask must be applied there too. ✅ done in PR.
  • Configuration change (rotation)SearchView reuses the same inner EditText across rotations; EnsureNoFullscreenFlag set once in ctor will persist. Re-application on UpdateReturnType is belt-and-braces.
  • Extract mode opt-in by user — no public MAUI API exposes this; force-on is acceptable.

Verdict

LGTM with minor concerns (confidence: high) — fix correctly targets the documented Android IME behaviour and is well-scoped. The SearchBarHandler2 mask change is theoretically dead code today (handler is not the default SearchBar path) but is a sensible defensive change for when material3 goes public. The main missed opportunity is that SearchBarHandler2 itself does not call EnsureNoFullscreenFlag on its inner MauiMaterialSearchBarTextInputEditText, so the bug will resurface as soon as material3 is enabled.

Test Type & Command

  • Detected test type: UITest (Appium) — src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
  • Command: pwsh eng/scripts/BuildAndRunHostApp.ps1 -Platform android -TestFilter Issue14708 (already run by gate)
  • Gate result: ✅ PASSED — without fix the screenshot comparison fails (full-screen black extract overlay differs from baseline); with fix it passes (inline keyboard with content visible behind it).

Platform

android (per PR scope — the bug is Android-only).


🔧 Fix — Analysis & Comparison

Try-Fix Phase Summary — PR #35197

Bug: Issue #14708 — Android SearchBar enters full-screen IME extract mode in landscape orientation.
Root cause (gate-confirmed): Inner EditText of the platform SearchView does not have ImeFlags.NoFullscreen (0x02000000) set on ImeOptions, so Android's IME defaults to extract mode in landscape.

All four candidates use the same flag (ImeFlags.NoFullscreen) and differ only in where and how it's applied. None of them disagrees with the root cause; the gate already validated it.

Cross-Pollination — Did models converge?

Yes — every candidate ended up at "OR NoFullscreen into ImeOptions of the inner search EditText, then mask the action bits when reading back". The differences are all about scope, idiom, and where the OR happens, not the fix itself. This convergence is expected given how narrow the Android API surface for this behaviour is.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #35197 Add EnsureNoFullscreenFlag extension; apply at MauiSearchView ctor + both UpdateReturnType overloads; mask in SearchBarHandler2.OnEditorAction. ✅ PASS (gate) 4 prod + 2 test Original PR — gate-verified.
pr-plus-reviewer Branch A (expert reviewer) PR fix + EOF newline restored + blank-line separator before new method in EditTextExtensions.cs. ✅ PASS (gate)¹ 4 prod + 2 test (cosmetic-only delta) Cosmetic only. Behaviourally identical to PR.
try-fix-1 claude-opus-4.6 Set NoFullscreen once in MauiSearchView ctor; OR-preserve high IME bits in both UpdateReturnType overloads (no new EditTextExtensions method); mask in SearchBarHandler2. 🟡 NOT-RUN² 3 prod Smaller surface, future-proof for any IME flag, no public-extension creep.
try-fix-2 claude-sonnet-4.6 Override MauiSearchView.OnCreateInputConnection to OR NoFullscreen into EditorInfo.ImeOptions; mask in SearchBarHandler2. 🟡 NOT-RUN² 2 prod Idiomatic Android entry point. Risk: AndroidX SearchView's inner SearchAutoComplete may not consult the parent override — unverified without on-device run.
try-fix-3 gpt-5.3-codex PR fix + extend to EntryHandler and EditorHandler (universal text-input fix). 🟡 NOT-RUN² 6 prod Bigger blast radius; addresses the same Android default that affects Entry/Editor. Larger scope than Issue #14708 asks for.
try-fix-4 gemini-3-pro-preview PR fix verbatim + apply EnsureNoFullscreenFlag in SearchBarHandler2.ConnectHandler (close the material3 gap). 🟡 NOT-RUN²,³ 4 prod (PR) + 1-line addition Removes "dead defensive code" smell (PR's mask change in SearchBarHandler2 becomes meaningful).

¹ The reviewer's edits are EOF-newline + blank-line — they don't change any expression; the gate result for pr carries over.
² UI-test rebuild + Android emulator run (~17 min × 2 phases per candidate) is not feasible within this review's wall-clock budget on the Linux CI runner. All four are design candidates with unified diffs against main. Their behavioural prediction is anchored by the gate-verified PR fix (same root cause + same flag).
³ The for-the-default-handler portion of try-fix-4 is byte-identical to the PR; the material3 addition is invisible to Issue14708 (which uses the default SearchBarHandler, not SearchBarHandler2).

Cross-Pollination Round

Model (intended) Round New idea? Details
claude-opus-4.6 (try-fix-1) 2 NO NEW IDEAS Considered: switching NoFullscreen for NoExtractUi — strictly weaker UX (still uses fullscreen layout, just hides the extract text view). Not pursued.
claude-sonnet-4.6 (try-fix-2) 2 NO NEW IDEAS Considered: WindowSoftInputMode at activity level — affects whole window, far too invasive. Not pursued.
gpt-5.3-codex (try-fix-3) 2 NO NEW IDEAS Considered: per-control opt-in API for fullscreen IME suppression — adds public surface for a fix that has no opt-out use case. Rejected.
gemini-3-pro-preview (try-fix-4) 2 NO NEW IDEAS Considered: Configuration.Orientation == Landscape conditional — NoFullscreen is a no-op in portrait anyway, conditional adds complexity without behavioural benefit. Rejected.

Exhausted: Yes — convergence after one round; no further independent fix shapes available given the bounded Android API.

Selected Fix

Winner: pr (the PR fix, equivalent to pr-plus-reviewer)

Rationale (full table in report/content.md):

  • Only gate-verified PASS candidate.
  • Functionally equivalent to pr-plus-reviewer (cosmetic delta only).
  • All 4 try-fix candidates are 🟡 NOT-RUN; per the user's tiebreaker rule "candidates that failed regression tests MUST be ranked lower than candidates that passed them", any candidate without a verified PASS ranks below the PR.
  • Among the design candidates, try-fix-4 is the most aligned (removes the dead-code smell on the material3 path) and is recommended as a follow-up improvement, but does not displace the PR.

Limitations of this run

  • try-fix-1..try-fix-4 were authored as independent diffs but not built or executed against an Android emulator in this session. The try-fix skill's empirical iteration loop is reduced to a code-level analysis here. The convergence of all four candidates on the same NoFullscreen flag (the single Android API for this behaviour) means the empirical risk to the PR's correctness is low.
  • Branch A (expert reviewer) ran the full multi-dimensional review with applied sandbox edits and inline-finding JSON — that part is real, not simulated.

📋 Report — Final Recommendation

Phase 3 Report — PR #35197

Bug: Issue #14708 — Android SearchBar enters full-screen IME extract mode in landscape orientation.
Platform reviewed: Android.
Gate result (provided): ✅ PASSED — Issue14708 UI test FAILs without the PR's fix and PASSes with it (16-min build/run × 2 phases on the local Android emulator pipeline).

Candidates evaluated

Candidate Status Test result Files changed (prod) Independent of PR?
pr Submitted ✅ PASS (gate) 4
pr-plus-reviewer Sandbox-applied ✅ PASS¹ 4 (1 cosmetic delta) No (cosmetic delta only)
try-fix-1 Design candidate 🟡 NOT-RUN 3 Yes
try-fix-2 Design candidate 🟡 NOT-RUN 2 Yes
try-fix-3 Design candidate 🟡 NOT-RUN 6 Yes
try-fix-4 Design candidate 🟡 NOT-RUN 4 (PR) + 1-line addition Yes

¹ EOF newline + blank-line separator only; no expression-level change → gate pass carries over.

Comparative analysis

Correctness

All six candidates target the same root cause and use the same Android IME flag (ImeFlags.NoFullscreen = 0x02000000). Convergence is expected — Android exposes no other supported API to suppress IME extract mode in landscape. The candidates differ in where and how the flag is applied:

  • pr / pr-plus-reviewer — explicit EnsureNoFullscreenFlag() extension method, called at every place ImeOptions is mutated for SearchBar's inner EditText.
  • try-fix-1 — same flag, applied once at MauiSearchView.Initialize; UpdateReturnType is upgraded to OR-preserve high IME bits so the flag survives subsequent return-type changes without explicit re-application.
  • try-fix-2 — flag set at the canonical Android hook (OnCreateInputConnection override on MauiSearchView).
  • try-fix-3 — same as PR plus extends to Entry and Editor handlers.
  • try-fix-4 — same as PR plus a one-line addition in SearchBarHandler2.ConnectHandler to also fix the material3 path.

Test coverage

  • The PR adds a screenshot UI test (Issue14708) that catches the bug visually (black extract overlay vs inline keyboard baseline). Reviewer noted minor stability concerns: retryTimeout: 2s may be tight on slow Android emulators, and searchBar2/searchBar3 are present on the host page but not exercised. Neither blocks merge.
  • The gate validated: ✅ test FAILS without fix, ✅ test PASSES with fix. This is the single strongest signal for ranking.
  • try-fix-1 is byte-equivalent in observable IME behaviour and would pass the same test.
  • try-fix-2 carries an empirical risk that AndroidX SearchView's inner SearchAutoComplete.OnCreateInputConnection doesn't consult the parent override; this could silently fail to set NoFullscreen. Without on-device verification, ranking cannot be raised.
  • try-fix-3 would pass Issue14708 (superset of PR) but expands behaviour on Entry/Editor whose own UI tests were not re-run by the gate; unverified regression risk.
  • try-fix-4 is byte-identical to PR for the default SearchBar path; the material3 addition is invisible to Issue14708.

Reviewer-feedback dimensions

The maui-expert-reviewer agent (Branch A) returned 0 errors / 0 warnings / 4 suggestions across the dimensions: platform-android, handler-lifecycle, public-api, regression, threading, testing, defensive-coding. Verdict: LGTM-with-minor, confidence: high. None of the suggestions blocks merge.

Dimension Concern
defensive-coding SearchBarHandler2.OnEditorAction masks ImeOptions but the handler never actually applies NoFullscreen. Today this works because MapReturnType routes through UpdateReturnType(EditText) which calls EnsureNoFullscreenFlag, but the protection is mapper-ordering-dependent. (→ try-fix-4 addresses this.)
testing searchBar2/searchBar3 declared but not tapped; retryTimeout: 2s is short for cold-start emulators.
platform-android searchView.ImeOptions is written without NoFullscreen while inner EditText has it — divergence may matter on configuration-change re-propagation.

Ranking

Per the user's tiebreaker rule, candidates that failed regression tests MUST rank below candidates that passed them. Inverting the rule for the available data: candidates with a gate-verified PASS rank above candidates that were not run.

Rank Candidate Why
1 pr ✅ Gate PASS. Minimal, idiomatic, well-scoped, well-tested.
1 (tie) pr-plus-reviewer Cosmetic-only delta; behaviourally identical to pr. Tie-broken in favour of pr because the cosmetic edits aren't required for correctness and the PR can land as-is.
3 try-fix-4 🟡 NOT-RUN. Best-aligned with PR; closes the material3 dead-code smell. Recommended as a follow-up, not a replacement.
4 try-fix-1 🟡 NOT-RUN. Smaller surface than PR; OR-preserve idiom is future-proof, but the PR's explicit-call style is more grep-able.
5 try-fix-3 🟡 NOT-RUN. Larger scope than Issue #14708 warrants; Entry/Editor paths unverified.
6 try-fix-2 🟡 NOT-RUN. Most idiomatic on paper but carries an unverified Android-call-path risk that AndroidX SearchView's inner EditText bypasses parent-view OnCreateInputConnection.

Recommendation

Winner: pr (equivalent to pr-plus-reviewer).

The PR is gate-verified and merge-quality. Branch A's expert reviewer found 0 errors / 0 warnings / 4 minor suggestions — all comment-only or follow-up scope. None of the four try-fix candidates is empirically tested in this session, so they cannot displace a gate-verified PASS.

Recommended follow-ups (do not block merge):

  1. Open a follow-up issue to apply EnsureNoFullscreenFlag in SearchBarHandler2.ConnectHandler (per try-fix-4 and the inline finding at SearchBarHandler2.Android.cs:258) before material3 SearchBar goes public in net11.
  2. Increase Issue14708.cs (Tests) retryTimeout from 2s to 5s for emulator stability.
  3. Optionally extend the same fix to Entry and Editor handlers (per try-fix-3 / inline findings) to prevent the same bug surfacing as new issues for those controls.

The 4 inline findings have been written to inline-findings.json for the inline-comment posting step.


@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented May 8, 2026

🤖 AI Summary

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

📊 Review Session0afc83b · committed the suggestion · 2026-05-08 11:21 UTC
🚦 Gate — Test Before & After Fix

Gate Result: ✅ PASSED

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

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

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

Time Elapsed 00:07:05.86
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.14048155
  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.14048155
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  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.14048155
  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.12]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.32]   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/08/2026 10:53:51 FixtureSetup for Issue14708(Android)
>>>>> 05/08/2026 10:53:54 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Start
>>>>> 05/08/2026 10:54:09 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Stop
>>>>> 05/08/2026 10:54:12 Log types: logcat, bugreport, server
  Failed SearchBarLandscapeShowsInlineKeyboardNotExtractMode [18 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: SearchBarLandscapeShowsInlineKeyboardNotExtractMode.png (5.85% 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
Test Run Failed.
     Failed: 1
 Total time: 35.5562 Seconds

🟢 With fix — 🖥️ Issue14708: PASS ✅ · 535s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  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.14048155
  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.14048155
  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.14048155
  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.14048155
  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.14048155
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.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.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.14048155
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.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.14048155
  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.14048155
  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.14048155
  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.14048155
  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.14048155
  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.14048155
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  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
  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

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

Time Elapsed 00:06:51.76
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.14048155
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.70-ci+azdo.14048155
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.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.14048155
  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.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.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
  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.11]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.32]   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/08/2026 11:02:54 FixtureSetup for Issue14708(Android)
>>>>> 05/08/2026 11:02:57 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Start
>>>>> 05/08/2026 11:03:06 SearchBarLandscapeShowsInlineKeyboardNotExtractMode Stop
  Passed SearchBarLandscapeShowsInlineKeyboardNotExtractMode [12 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 27.9115 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 — Category Detection

Detected UI test categories: SearchBar,ViewBaseTests

🧪 UI Test Execution Results

FAILED — 1 passed, 1 failed, 0 skipped (platform: android)

Category Result Tests Duration Notes
SearchBar ❌ FAILED 41/42 (1 ❌) 1685.9s exit code 1, names truncated
ViewBaseTests ✅ PASSED 118/119 ✓ 863.2s names truncated
Show 10 of 159 passed test name(s) — stdout was truncated, full list in build log

SearchBar

  • SearchBar_SetTextAndVerticalTextAlignment_VerifyVisualState (6 s)
  • SearchBar_SetPlaceholderColorAndTextColor_VerifyVisualState (5 s)
  • SearchBar_SetShadow_VerifyVisualState (6 s)
  • SearchBar_SetTextAndCharacterSpacing_VerifyVisualState (6 s)
  • SearchBar_SetTextAndTextTransform (5 s)

ViewBaseTests

  • VisualTransform_ScaleWithAnchorXAndRotationY (7 s)
  • VisualTransform_ScaleX (5 s)
  • VisualTransform_ScaleXWithAnchorYAndRotationY (7 s)
  • VisualTransform_ScaleY (5 s)
  • VisualTransform_ScaleYWithAnchorXAndRotationY (7 s)

Failures here are informational only — they do not block the gate or affect try-fix candidate scoring.

ℹ️ This section was reconstructed from the build artifact (35197 build) after the run completed.


🔍 Regression Cross-Reference

🔍 Regression Cross-Reference

🟢 No regression risks detected. No labeled bug-fix PRs in the last 6 months touched the modified files.


🔍 Pre-Flight — Context & Validation

Issue: #14708 - [Android] Investigate SearchBar presentation in horizontal screen orientation
PR: #35197 - [Android] Fix SearchBar IME full-screen extract mode in landscape orientation
Platforms Affected: Android (test exercised on iOS too)
Files Changed: 4 implementation, 5 test (incl. 3 snapshot PNGs)
Base branch: main
Head branch: Fix-14708
Author: SubhikshaSf4851 (community ✨, partner/syncfusion)

Bug Summary

On Android, when the user taps a SearchBar in landscape orientation, the IME (soft keyboard) enters "full-screen extract mode" — the EditText balloons to fill the screen, hides app content, and shows a default Android black-on-gray SEARCH button. The expected behavior is for the keyboard to remain inline. The bug only triggers when interaction starts in landscape; rotating mid-interaction keeps the inline UI.

Root Cause

MauiSearchView's inner EditText (and the standalone SearchView codepath in SearchBarHandler2) never set the ImeFlags.NoFullscreen flag on ImeOptions. The Android InputMethodManager defaults to extract mode in landscape unless IME_FLAG_NO_EXTRACT_UI (0x02000000) is set.

A secondary problem: SearchBarHandler2.OnEditorAction reads PlatformView.EditText.ImeOptions and compares it directly to ImeAction.Done etc. Once NoFullscreen is OR'd into ImeOptions, the action bits are masked by extra flag bits and the comparison fails.

Files Changed (impl)

File Change
src/Core/src/Platform/Android/EditTextExtensions.cs Adds EnsureNoFullscreenFlag() extension that ORs ImeFlags.NoFullscreen into editText.ImeOptions.
src/Core/src/Platform/Android/MauiSearchView.cs Calls EnsureNoFullscreenFlag() on _queryEditor after init. Adds using Android.Views.InputMethods;.
src/Core/src/Platform/Android/SearchViewExtensions.cs UpdateReturnType(SearchView) now also sets ImeOptions on the inner EditText with NoFullscreen; UpdateReturnType(EditText) calls EnsureNoFullscreenFlag().
src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs Masks ImeOptions with ImeMaskAction before comparing to action constants in OnEditorAction.

Files Changed (test)

  • src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs — sample page with SearchBar + Label.
  • src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs — UI test rotates to landscape, taps SearchBar, asserts via screenshot.
  • 3 snapshot PNGs (Android, iOS, iOS-26).

Edge Cases / Reviewer Concerns Imported

  • Reviewer (Copilot) suggested #if IOS symbol mismatch; author chose to keep both Android+iOS for visual regression.
  • Reviewer flagged Thread.Sleep(1000); author claims to have replaced it.
  • All inline reviewer comments addressed by author per latest comments.

Key Findings

  • EnsureNoFullscreenFlag is a one-way OR — never cleared. That's correct for current usage (we always want NoFullscreen on a SearchBar EditText).
  • The mask ImeMaskAction (0x000000FF) is the correct constant to isolate action bits from flags (0xFF000000).
  • UpdateReturnType(SearchView) writes ImeOptions twice (on SearchView, then on inner EditText). The double-write is intentional per the inline comments — Android sometimes re-propagates from SearchView back to the inner EditText.
  • File EditTextExtensions.cs ends without trailing newline (pre-existing pattern in Microsoft.Maui.Platform).
  • SearchViewExtensions.cs adds an extra blank line at end of method — cosmetic.

Code Review Summary

Verdict: LGTM (will be refined by Branch A expert evaluation)
Confidence: medium
Errors: 0 | Warnings: 0 | Suggestions: 1

Code review pre-classification (full deep review delegated to Branch A maui-expert-reviewer):

  • 💡 The MauiSearchView constructor and UpdateReturnType paths both ensure NoFullscreen, but SearchBarHandler2 (Material) only fixes the action-mask bug — its EditText initialization should also be checked to confirm NoFullscreen is set there. Reading the diff, SearchBarHandler2 does not appear to set NoFullscreen on its own EditText. This may be a gap if the Material SearchBar is used (M3 styles).

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #35197 Set ImeFlags.NoFullscreen on inner EditText + mask action bits in handler ✅ PASSED (Gate) 4 impl files Original PR

🔧 Fix — Analysis & Comparison

Try-Fix Aggregate — 4 Independent Candidates

Each candidate explores a different reviewer dimension lens against the same bug (Android SearchBar landscape IME extract mode). Tests cannot be empirically run in this Linux orchestrator container (no Android emulator), so all candidates report Blocked for runtime validation. The PR's gate already proved the regression test catches the bug and the PR's fix passes.

Candidates Summary

# Candidate Reviewer Dimension Lens Strategy Files Changed Test Result
1 try-fix-1 #2 Hot Path / #5 Mapper Set NoFullscreen once at Initialize + ConnectHandler; revert per-update OR-ing; read ReturnType.ToPlatform() in handler 3 (revert 2 of PR's, add 1 line in handler ConnectHandler) Blocked
2 try-fix-2 #5 Mapper / #11 Lifecycle Use Mapper.AppendToMapping("ReturnType", …) so the flag is re-applied via mapper system; revert SearchViewExtensions 3 (revert SearchViewExtensions, add static ctor in 2 handlers) Blocked
3 try-fix-3 #15 API Design / #14 Public API Replace bare EnsureNoFullscreenFlag with intent-named SetSearchImeOptions(action) + GetCurrentImeAction(); consolidate callsites 4 (refactor of PR's helpers + callsites) Blocked
4 try-fix-4 #20 Regression Pattern / #6 Platform Override OnCreateInputConnection on MauiSearchView and Material EditText so flag is set in EditorInfo (Android-canonical) 2 (no extension method needed, revert most of PR) Blocked
PR pr (current PR fix) OR NoFullscreen flag at every UpdateReturnType callsite + add defensive ImeMaskAction mask in OnEditorAction 4 ✅ PASSED (Gate)

Cross-Pollination Round (synthesized)

After Round 1, key insights:

  • try-fix-1 & try-fix-2 agree the action-bit-mask in OnEditorAction is unnecessary if you never read from a polluted field. Use ReturnType.ToPlatform() instead.
  • try-fix-3 points out the helper API in PR is named for mechanism (EnsureNoFullscreenFlag) instead of intent; cross-pollinated suggestion: rename to SetSearchImeOptions even if other implementation details differ.
  • try-fix-4 identifies a true Android-framework-canonical layer fix that none of the others use, but has the highest verification risk because we couldn't empirically confirm OnCreateInputConnection is invoked on MauiSearchView (vs. its inner EditText) in a no-emulator environment.

No new ideas surfaced from a 2nd cross-pollination round. The 4 lenses produced 4 structurally different fixes; further iteration would only refine wording.

Selection (preliminary — Phase 3 will confirm against PR + pr-plus-reviewer)

  • try-fix-1 is the strongest evolution of the PR (smaller diff, fixes a real gap in SearchBarHandler2) without disrupting the architecture.
  • try-fix-4 is the strongest theoretical approach but unverified.
  • try-fix-2 and try-fix-3 are aesthetically cleaner but are sideways moves (similar net effect to PR, refactored).

Per the task instructions ("candidates that failed regression tests MUST be ranked lower than candidates that passed them"), only the pr candidate has a verified ✅ test result. All try-fix candidates are Blocked (not failed — but unverified). Per ranking rules, pr and pr-plus-reviewer outrank all try-fix candidates unless one of them produced and passed an actual test run, which none did.

Likely winner: pr or pr-plus-reviewer, depending on Branch A reviewer findings. Try-fix candidates are documented for future reference / follow-up PRs.

Exhausted: Yes (4 dimension lenses + cross-pollination converged).


📋 Report — Final Recommendation

PR #35197 — Comparative Analysis & Final Recommendation

Candidates Evaluated

Candidate Source Test Result Diff Size Net Quality
pr Original PR fix PASSED (Gate) — verified empirically +25 / −1 in 4 impl files High — correct, well-targeted
pr-plus-reviewer PR + 1-line EditText.UpdateReturnType(IEntry) extension to fix Entry/Editor consistency gap ⚪ Not run (additive, low-risk) PR + 1 line High — closes scope inconsistency reviewer flagged as ⚠️ moderate
try-fix-1 Hot-path lens — set NoFullscreen once at Initialize/ConnectHandler; revert per-update OR-ing; read ReturnType.ToPlatform() in handler ⛔ Blocked (no Android emulator) Smaller (3 files) Medium — clever, but relies on assumption that EditText.ImeOptions field persists across config changes (PR's defensive every-update OR is precisely there to guard against this)
try-fix-2 Mapper-level lens — Mapper.AppendToMapping("ReturnType", …) ⛔ Blocked Similar to PR Medium — sideways move; correctness depends on every consumer keeping the mapper
try-fix-3 API-design lens — replace EnsureNoFullscreenFlag with intent-named SetSearchImeOptions(action) + GetCurrentImeAction() ⛔ Blocked Refactor of PR Medium-High — better encapsulation, but pure API rename of PR's mechanism
try-fix-4 Regression-pattern lens — override OnCreateInputConnection so flag lives on EditorInfo ⛔ Blocked Smallest (2 files) High in theory; High verification riskMauiSearchView.OnCreateInputConnection may not be invoked (the inner EditText handles focus). Without a device, can't confirm

Ranking Rules Applied

The task spec mandates: "Candidates that failed regression tests MUST be ranked lower than candidates that passed them." Only pr has a verified ✅ PASS. pr-plus-reviewer is pr plus an additive 1-line consistency fix that does not touch the regression-tested code path, so it is the only other candidate with a credible "passes the same regression test" guarantee. All try-fix-* candidates are Blocked (untested) — they rank below the empirically-validated PR-derived candidates.

Head-to-Head: pr vs pr-plus-reviewer

The expert reviewer's verdict on the PR is LGTM with minor follow-up — no ❌ Errors, 2 ⚠️ Warnings, 4 💡 Nitpicks. The most impactful warning is the Entry/Editor scope gap: the same Android IME_FLAG_NO_FULLSCREEN fix would benefit Entry and Editor controls since the bug class affects any focused EditText in landscape, but the PR only patches the SearchBar paths.

pr-plus-reviewer adds one line (editText.EnsureNoFullscreenFlag() in EditTextExtensions.UpdateReturnType(IEntry)) which:

  • ✅ Fixes the consistency gap in the same surgical style.
  • ⚠️ Expands scope beyond what the PR title and description claim.
  • ⚠️ For multi-line Editor, some users may prefer extract mode in landscape (more typing area). The reviewer flagged this as a decision the author should make.

Because the PR's stated scope is "SearchBar" and the author explicitly chose that scope, applying pr-plus-reviewer would unilaterally widen the contract beyond what was reviewed/discussed. The cleaner path is to merge pr as-is and open a follow-up issue for Entry/Editor consistency where the scope decision can be made deliberately.

Winner: pr

The original PR fix is correct, well-targeted, and verified by the gate run. The reviewer's findings are advisory follow-ups, not blockers. Specifically:

  • ⚠️ Entry/Editor scope gap → file as follow-up issue; deliberate scope decision needed.
  • ⚠️ OnEditorAction mask lock-in test → small follow-up; current behavior is correct.
  • 💡 Redundant double-write in SearchView.UpdateReturnType → cosmetic.
  • 💡 Helper contract fragility → consider in a future refactor pass.
  • 💡 Unused secondary SearchBars in test page → minor cleanup.
  • 💡 Snapshot-only assertion → consider non-visual assertion as backup.

None of these block merge. The PR is ready for human approval.

Try-Fix Verdicts (for the record)

  • try-fix-1 would be a good follow-up refactor if real-device testing confirms EditText.ImeOptions persists across configuration changes — it would eliminate ~10 lines of code from the PR. Cannot be validated here.
  • try-fix-2 is a stylistic preference; net behavior is the same as PR.
  • try-fix-3 API improvement is a worthwhile follow-up (helper named for intent, not mechanism), but does not change correctness.
  • try-fix-4 is the most architecturally-correct approach but carries the highest verification risk and would need empirical confirmation that OnCreateInputConnection is invoked at the right level.

Final Recommendation

Merge PR #35197 as-is. Open follow-up issues for:

  1. Entry/Editor consistency (apply IME_FLAG_NO_FULLSCREEN to Entry; decide on Editor).
  2. Consider refactoring EnsureNoFullscreenFlagSetSearchImeOptions(action) per try-fix-3.
  3. Add a non-visual assertion to the regression test (read back EditText.ImeOptions & NoFullscreen != 0).

Copy link
Copy Markdown
Collaborator

@MauiBot MauiBot left a comment

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.

var editText = searchView.GetFirstChildOfType<EditText>();
if (editText is not null)
{
editText.ImeOptions = searchBar.ReturnType.ToPlatform();
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.

[minor] Complexity ReductioneditText.ImeOptions = searchBar.ReturnType.ToPlatform(); immediately after searchView.ImeOptions = (int)searchBar.ReturnType.ToPlatform(); on line 244 writes the same value to the same underlying EditText (SearchView.setImeOptions forwards to the inner query text view). The duplicate assignment isn't incorrect, but is redundant — only searchView.ImeOptions = … plus the subsequent editText.EnsureNoFullscreenFlag() is needed. Consider dropping line 250 or adding a comment explaining why the explicit write is required (e.g., a known API-level case where the cascade doesn't happen).

// 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);
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.

[minor] MaintainabilityEnsureNoFullscreenFlag is a defensive helper but the contract is fragile: any future code path that assigns editText.ImeOptions = … without calling this helper afterwards will silently re-introduce the bug. Consider either (a) renaming/encapsulating into a SetImeOptionsPreservingFlags(this EditText, ImeAction) helper that callers must use instead of touching ImeOptions directly, or (b) adding a code comment on ImeOptions usages elsewhere pointing to this helper. Today the contract is implicit and only documented by the call sites that happen to remember it.

AutomationId = "SearchBarControl"
};

var searchBar2 = new SearchBar
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.

[minor] Test hygienesearchBar2 and searchBar3 are added to the page but the UI test only interacts with _primarySearchBar. They make the snapshot baseline dependent on rendering of additional SearchBars (which is fine for visual-diff coverage), but they look unused at first glance and increase the surface for unrelated layout regressions to flake this test. Either drop them or extend the test to focus each one and verify it also stays in inline-keyboard mode (which is the more valuable coverage).

// 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);
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.

[moderate] Logic and Correctness — verify against original repro — The mask (int)PlatformView.EditText.ImeOptions & (int)ImeAction.ImeMaskAction is correct given that the EditText now has NoFullscreen (0x02000000) OR'd into ImeOptions. Please confirm ImeAction.ImeMaskAction value is 0xFF (the standard Android constant) on every Android API the library targets — if for any reason the binding exposes it as a different mask, the action comparison silently changes meaning on that API. A short xUnit/integration assertion (e.g., apply the flag, read back, mask, compare to ImeAction.Search) would lock this in. The PR's UI test only verifies the visual symptom; it does not cover the EditorAction branch this mask was added to fix.

// 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.
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.

[minor] Regression coverage — The test relies entirely on VerifyScreenshot to catch IME extract mode. That works, but on Android the same regression could be detected more deterministically by asserting imm.IsFullscreenMode == false (or by reading back EditText.ImeOptions & ImeFlags.NoFullscreen != 0) via a small platform helper exposed for testing. Snapshot-only coverage will be sensitive to keyboard skin / Android system theme changes on the test image. Consider adding a non-visual assertion as the primary check and keeping the screenshot as a backup.

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-win AI found a better alternative fix than the PR s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Android] Investigate SearchBar presentation in horizontal screen orientation

6 participants