-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[Android] [Windows] Fixed text deletion via the clear icon in SearchBar when IsReadOnly is true #29592
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[Android] [Windows] Fixed text deletion via the clear icon in SearchBar when IsReadOnly is true #29592
Changes from all commits
e881b5f
5d788d5
e01124d
44f80a7
b8c2ac3
eff22f6
4721153
6e0617c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| namespace Maui.Controls.Sample.Issues; | ||
|
|
||
| [Issue(IssueTracker.Github, 29547, "SearchBar with IsReadOnly=True still allows text deletion While pressing delete icon", PlatformAffected.Android)] | ||
| public class Issue29547 : ContentPage | ||
| { | ||
| public Issue29547() | ||
| { | ||
| var searchBar = new SearchBar | ||
| { | ||
| Text = "Search", | ||
| IsReadOnly = true, | ||
| AutomationId = "searchbar" | ||
| }; | ||
|
|
||
| var grid = new Grid(); | ||
| grid.Children.Add(searchBar); | ||
| Content = grid; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| using NUnit.Framework; | ||
| using UITest.Appium; | ||
| using UITest.Core; | ||
|
|
||
| namespace Microsoft.Maui.TestCases.Tests.Issues; | ||
|
|
||
| public class Issue29547 : _IssuesUITest | ||
| { | ||
| public override string Issue => "SearchBar with IsReadOnly=True still allows text deletion While pressing delete icon"; | ||
|
|
||
| public Issue29547(TestDevice device) | ||
| : base(device) | ||
| { } | ||
|
|
||
| [Test] | ||
| [Category(UITestCategories.SearchBar)] | ||
| public void VerifySearchBarDeleteIconBehavior() | ||
| { | ||
| App.WaitForElement("searchbar"); | ||
| App.TapSearchBarClearButton("searchbar"); | ||
| VerifyScreenshot(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,19 +16,26 @@ public static void InvalidateAttachedProperties(DependencyObject obj) | |||||||||||||||||||||||||||||||
| public static bool GetIsReadOnly(DependencyObject obj) => | ||||||||||||||||||||||||||||||||
| (bool)obj.GetValue(IsReadOnlyProperty); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| public static void SetIsReadOnly(DependencyObject obj, bool value) => | ||||||||||||||||||||||||||||||||
| obj.SetValue(IsReadOnlyProperty, value); | ||||||||||||||||||||||||||||||||
| public static void SetIsReadOnly(DependencyObject obj, bool value) | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| if (obj is FrameworkElement element && element.IsLoaded) | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| obj.SetValue(IsReadOnlyProperty, value); | ||||||||||||||||||||||||||||||||
|
Comment on lines
+21
to
+23
|
||||||||||||||||||||||||||||||||
| if (obj is FrameworkElement element && element.IsLoaded) | |
| { | |
| obj.SetValue(IsReadOnlyProperty, value); | |
| obj.SetValue(IsReadOnlyProperty, value); | |
| if (obj is FrameworkElement element) | |
| { | |
| if (element.IsLoaded) | |
| { | |
| OnIsReadOnlyPropertyChanged(obj, new DependencyPropertyChangedEventArgs(IsReadOnlyProperty, null, value)); | |
| } | |
| else | |
| { | |
| element.Loaded += OnElementLoaded; | |
| } |
Copilot
AI
May 20, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes the default of IsReadOnly from true to false, which can be a breaking change for consumers relying on the old default. Please confirm this aligns with the minor version policy or bump the major version.
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2671,6 +2671,33 @@ public static IUIElement GetShellSearchHandler(this IApp app) | |||||||||||
| return element; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /// <summary> | ||||||||||||
| /// Taps the clear button in a search bar control with platform-specific implementations. | ||||||||||||
| /// </summary> | ||||||||||||
| /// <param name="app">Represents the main gateway to interact with an app.</param> | ||||||||||||
| /// <param name="automationId">The automation ID of the search bar.</param> | ||||||||||||
| /// <param name="timeout">Optional timeout for waiting for the clear button. Default is null, which uses the default timeout.</param> | ||||||||||||
| public static void TapSearchBarClearButton(this IApp app, string automationId, TimeSpan? timeout = null) | ||||||||||||
| { | ||||||||||||
| if (app is AppiumAndroidApp) | ||||||||||||
| { | ||||||||||||
| app.WaitForElement(AppiumQuery.ByXPath("//android.widget.ImageView[@content-desc='Clear query']"), timeout: timeout); | ||||||||||||
| app.Tap(AppiumQuery.ByXPath("//android.widget.ImageView[@content-desc='Clear query']")); | ||||||||||||
| } | ||||||||||||
| else if (app is AppiumIOSApp || app is AppiumCatalystApp) | ||||||||||||
| { | ||||||||||||
| app.WaitForElement("Clear text", timeout: timeout); | ||||||||||||
| app.Tap("Clear text"); | ||||||||||||
| } | ||||||||||||
| else if (app is AppiumWindowsApp) | ||||||||||||
| { | ||||||||||||
| var searchBar = app.WaitForElement(AppiumQuery.ByAccessibilityId(automationId), timeout: timeout); | ||||||||||||
| var rect = searchBar.GetRect(); | ||||||||||||
| app.Tap(automationId); | ||||||||||||
| app.TapCoordinates(rect.Right - 84, rect.Y + rect.Height / 2); | ||||||||||||
|
Comment on lines
+2696
to
+2697
|
||||||||||||
| app.Tap(automationId); | |
| app.TapCoordinates(rect.Right - 84, rect.Y + rect.Height / 2); | |
| var clearButtonOffset = rect.Width * 0.1; // Assuming the clear button is 10% of the search bar's width | |
| app.Tap(automationId); | |
| app.TapCoordinates(rect.Right - clearButtonOffset, rect.Y + rect.Height / 2); |
Uh oh!
There was an error while loading. Please reload this page.