Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue20348.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 20348, "SearchBar text incorrectly copied between multiple SearchBars on Android after back navigation", PlatformAffected.Android)]
public class Issue20348 : NavigationPage
{
public Issue20348() : base(new MainPage())
{
}

public class MainPage : ContentPage
{
public MainPage()
{
SearchBar firstSearchBar = new SearchBar
{
AutomationId = "FirstSearchBar"
};

Label firstSearchBarTextLabel = new Label
{
AutomationId = "FirstSearchBarText",
Text = "Pass"
};

firstSearchBar.TextChanged += (s, e) =>
{
firstSearchBarTextLabel.Text = string.IsNullOrEmpty(e.NewTextValue)
? "Pass"
: "Fail";
};
Comment on lines +25 to +30
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

FirstSearchBarText is updated only via firstSearchBar.TextChanged. If the Android state-restore path updates the platform text without raising the managed TextChanged event (or does so before the handler is attached in future refactors), this issue page can show "Pass" while the first SearchBar actually contains leaked text, making the UI test a false negative. Consider also updating the label based on firstSearchBar.Text in OnAppearing (or after returning from navigation).

Copilot uses AI. Check for mistakes.

SearchBar secondSearchBar = new SearchBar
{
AutomationId = "SecondSearchBar"
};

Button navigateButton = new Button
{
Text = "Navigate",
AutomationId = "NavigateButton"
};

navigateButton.Clicked += async (s, e) =>
{
await Navigation.PushAsync(new SecondPage());
};

Label descriptionLabel = new Label
{
Text = "Test passes if SecondSearchBar text is NOT applied to FirstSearchBar after typing in SecondSearchBar, navigating to page 2, and pressing back.",
FontSize = 12,
TextColor = Colors.Gray,
HorizontalTextAlignment = TextAlignment.Center
};

Content = new VerticalStackLayout
{
Padding = 20,
Spacing = 10,
Children = { descriptionLabel, firstSearchBar, firstSearchBarTextLabel, secondSearchBar, navigateButton }
};
}
}

public class SecondPage : ContentPage
{
public SecondPage()
{
Title = "Second Page";
Content = new Label
{
Text = "Second Page",
AutomationId = "SecondPageLabel",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue20348 : _IssuesUITest
{
public override string Issue => "SearchBar text incorrectly copied between multiple SearchBars on Android after back navigation";

public Issue20348(TestDevice device) : base(device) { }

[Test]
[Category(UITestCategories.SearchBar)]
public void SearchBarTextShouldNotBleedToOtherInstances()
{
App.WaitForElement("FirstSearchBar");
App.WaitForElement("SecondSearchBar");

App.EnterText("SecondSearchBar", "TestText");
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

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

After App.EnterText("SecondSearchBar", ...), the soft keyboard may obscure NavigateButton on smaller devices, making App.Tap("NavigateButton") flaky. Consider dismissing the keyboard (e.g., App.DismissKeyboard()) and/or waiting for NavigateButton to be visible before tapping.

Suggested change
App.EnterText("SecondSearchBar", "TestText");
App.EnterText("SecondSearchBar", "TestText");
App.DismissKeyboard();
App.WaitForElement("NavigateButton");

Copilot uses AI. Check for mistakes.
App.Tap("NavigateButton");

App.WaitForElement("SecondPageLabel");
this.Back();
App.WaitForElement("FirstSearchBarText");

var result = App.FindElement("FirstSearchBarText").GetText();
Assert.That(result, Is.EqualTo("Pass"),
"First SearchBar should be empty after back navigation — Android state save/restore should not bleed text from other SearchBar instances");
}
}
10 changes: 10 additions & 0 deletions src/Core/src/Platform/Android/MauiSearchView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ void Initialize()

_queryEditor = this.GetFirstChildOfType<EditText>();

// Disable Android's built-in instance state saving on the internal EditText
// to prevent query text from being incorrectly restored across multiple
// SearchView instances during navigation. The EditText shares a fixed
// resource ID (search_src_text) across all SearchViews, causing state
// to bleed between instances.
if (_queryEditor is not null)
{
_queryEditor.SaveEnabled = false;
}

if (_queryEditor?.LayoutParameters is LinearLayout.LayoutParams layoutParams)
{
layoutParams.Height = LinearLayout.LayoutParams.MatchParent;
Expand Down
Loading