[Android] Fix SearchBar IME full-screen extract mode in landscape orientation#35197
[Android] Fix SearchBar IME full-screen extract mode in landscape orientation#35197SubhikshaSf4851 wants to merge 3 commits intodotnet:mainfrom
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35197Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35197" |
|
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. |
There was a problem hiding this comment.
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.NoFullscreenwhen setting IME options forSearchView/EditTextused bySearchBar. - Mask IME flags when determining the current IME action in
SearchBarHandler2editor-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. |
b7e5ff4 to
cd4522b
Compare
MauiBot
left a comment
There was a problem hiding this comment.
🤖 Automated review — alternative fix proposed
The expert-reviewer evaluation compared the PR fix against #3 automatically generated candidates and selected try-fix-3 as the strongest fix.
Why: try-fix-3 is the most complete candidate: it shares the correct core fix as the PR but uniquely covers the UpdateKeyboard path for OEM robustness, introduces a shared s_noFullscreenFlag constant to eliminate triple-site cast duplication, adds explanatory comments for the ImeMaskAction masking, fixes the wrong #if ANDROID || iOS platform guard to #if ANDROID, replaces Thread.Sleep with a deterministic WaitForElement functional assertion, removes deprecated LayoutOptions.FillAndExpand, and removes dead code from the HostApp page.
Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.
Candidate diff (`try-fix-3`)
diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
index 19a89383a4..a1fdf00ec5 100644
--- a/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
+++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue14708.cs
@@ -5,19 +5,9 @@ namespace Maui.Controls.Sample.Issues;
[Issue(IssueTracker.Github, 14708, "Android SearchBar in landscape shows full-screen IME extract mode", PlatformAffected.Android)]
public class Issue14708 : ContentPage
{
- Label _searchTextLabel;
- SearchBar _primarySearchBar;
-
public Issue14708()
{
- _searchTextLabel = new Label
- {
- Text = "Search text: (none)",
- AutomationId = "SearchTextLabel",
- FontSize = 13
- };
-
- _primarySearchBar = new SearchBar
+ var primarySearchBar = new SearchBar
{
Text = "Hello, landscape!",
Placeholder = "Tap here in landscape - keyboard should be inline",
@@ -30,7 +20,6 @@ public class Issue14708 : ContentPage
AutomationId = "SearchBar2"
};
-
var searchBar3 = new SearchBar
{
Text = "Hello, landscape!",
@@ -38,10 +27,9 @@ public class Issue14708 : ContentPage
AutomationId = "SearchBar3"
};
-
Content = new ScrollView
{
- VerticalOptions = LayoutOptions.FillAndExpand,
+ VerticalOptions = LayoutOptions.Fill,
Content = new VerticalStackLayout
{
Padding = new Thickness(16),
@@ -55,8 +43,7 @@ public class Issue14708 : ContentPage
"NOT as a full-screen black overlay.",
HorizontalTextAlignment = TextAlignment.Center
},
- _primarySearchBar,
- _searchTextLabel,
+ primarySearchBar,
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
new Label { Text = "Additional SearchBars:", FontAttributes = FontAttributes.Italic, FontSize = 13 },
searchBar2,
diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
index 4780e95bba..3cedf18a9d 100644
--- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
+++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue14708.cs
@@ -1,4 +1,4 @@
-#if ANDROID || iOS // Orientation changes and IME behavior are only relevant on mobile platforms
+#if ANDROID // Orientation changes and IME extract-mode behavior are Android-specific
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;
@@ -29,8 +29,9 @@ public class Issue14708 : _IssuesUITest
// Tap the primary SearchBar to open the keyboard
App.Tap("SearchBarControl");
- // Wait a moment for keyboard to appear
- Thread.Sleep(1000);
+ // Verify SearchBarControl is still accessible after tap - in extract mode the page
+ // content is hidden by the full-screen IME overlay, making the element unreachable.
+ App.WaitForElement("SearchBarControl");
// In the unfixed state, Android enters IME extract mode in landscape:
// a full-screen black overlay replaces the inline keyboard and covers all
diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
index 233641da4e..372690ed17 100644
--- a/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
+++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler2.Android.cs
@@ -252,6 +252,8 @@ internal class SearchBarHandler2 : ViewHandler<ISearchBar, MauiMaterialSearchBar
{
var actionId = e.ActionId;
var evt = e.Event;
+ // Mask out ImeFlags (e.g. ImeFlags.NoFullscreen) that are OR'd into ImeOptions to prevent
+ // landscape extract mode. Only the action bits matter for enter-key dispatch comparisons.
ImeAction currentInputImeFlag = (ImeAction)((int)PlatformView.EditText.ImeOptions & (int)ImeAction.ImeMaskAction);
diff --git a/src/Core/src/Platform/Android/MauiSearchView.cs b/src/Core/src/Platform/Android/MauiSearchView.cs
index d978e491a1..18eefc3e85 100644
--- a/src/Core/src/Platform/Android/MauiSearchView.cs
+++ b/src/Core/src/Platform/Android/MauiSearchView.cs
@@ -31,6 +31,8 @@ namespace Microsoft.Maui.Platform
if (_queryEditor is not null)
{
_queryEditor.SaveEnabled = false;
+ // Prevent Android from entering full-screen IME extract mode in landscape
+ // orientation (GitHub issue #14708).
_queryEditor.ImeOptions = (ImeAction)((int)_queryEditor.ImeOptions | (int)ImeFlags.NoFullscreen);
}
diff --git a/src/Core/src/Platform/Android/SearchViewExtensions.cs b/src/Core/src/Platform/Android/SearchViewExtensions.cs
index ad864ac7f1..ec10fb1230 100644
--- a/src/Core/src/Platform/Android/SearchViewExtensions.cs
+++ b/src/Core/src/Platform/Android/SearchViewExtensions.cs
@@ -18,6 +18,12 @@ namespace Microsoft.Maui.Platform
{
static readonly int[] s_DisabledState = [-AAttribute.StateEnabled];
static readonly int[] s_EnabledState = [AAttribute.StateEnabled];
+
+ // Cast ImeFlags.NoFullscreen to ImeAction so it can be OR'd with other ImeAction values.
+ // This flag prevents Android from entering full-screen IME extract mode in landscape
+ // orientation (GitHub issue #14708).
+ static readonly ImeAction s_noFullscreenFlag = (ImeAction)(int)ImeFlags.NoFullscreen;
+
public static void UpdateText(this SearchView searchView, ISearchBar searchBar)
{
searchView.SetQuery(searchBar.Text, false);
@@ -234,12 +240,15 @@ namespace Microsoft.Maui.Platform
public static void UpdateKeyboard(this SearchView searchView, ISearchBar searchBar)
{
searchView.SetInputType(searchBar);
+ // Re-apply NoFullscreen after input type change to guard against OEM-specific
+ // implementations that may reset ImeOptions when InputType changes (issue #14708).
+ searchView.ImeOptions = (int)((ImeAction)searchView.ImeOptions | s_noFullscreenFlag);
}
public static void UpdateReturnType(this SearchView searchView, ISearchBar searchBar)
{
searchView.SetInputType(searchBar);
- searchView.ImeOptions = (int)((ImeAction)searchBar.ReturnType.ToPlatform() | (ImeAction)(int)ImeFlags.NoFullscreen);
+ searchView.ImeOptions = (int)(searchBar.ReturnType.ToPlatform() | s_noFullscreenFlag);
}
internal static void SetInputType(this SearchView searchView, ISearchBar searchBar, EditText? editText = null)
@@ -394,7 +403,7 @@ namespace Microsoft.Maui.Platform
internal static void UpdateReturnType(this EditText editText, ISearchBar searchBar)
{
- editText.ImeOptions = (ImeAction)((int)searchBar.ReturnType.ToPlatform() | (int)ImeFlags.NoFullscreen);
+ editText.ImeOptions = searchBar.ReturnType.ToPlatform() | s_noFullscreenFlag;
// Restart the input on the current focused EditText
InputMethodManager? imm = (InputMethodManager?)editText.Context?.GetSystemService(Context.InputMethodService);
kubaflo
left a comment
There was a problem hiding this comment.
Could you please try ai's suggestions?
MauiBot
left a comment
There was a problem hiding this comment.
🤖 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);
}
}
}
MauiBot
left a comment
There was a problem hiding this comment.
🤖 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);
+ }
}
}
|
@kubaflo I have updated the changes |
MauiBot
left a comment
There was a problem hiding this comment.
🤖 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)
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
SearchBarin 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:
MauiSearchViewinitialization to set theNoFullscreenIME flag on theEditText, preventing the keyboard from switching to full-screen extract mode in landscape orientation.UpdateReturnTypemethods inSearchViewExtensions.csto always include theNoFullscreenIME flag when setting IME options for bothSearchViewandEditText. [1] [2]SearchBarHandler2.Android.csto mask out unwanted IME flags and only use the action bits.Testing improvements:
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.Codebase maintenance:
InputMethodsimport toMauiSearchView.csfor clarity and future maintainability.Issues Fixed
Fixes #14708
Tested the behavior in the following platforms