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
21 changes: 21 additions & 0 deletions src/Controls/src/Core/SearchBar/SearchBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Input;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Controls.Internals;

using Microsoft.Maui.Graphics;
Expand Down Expand Up @@ -115,6 +116,26 @@ public SearchBar()
_platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<SearchBar>>(() => new PlatformConfigurationRegistry<SearchBar>(this));
}

private protected override void OnHandlerChangingCore(HandlerChangingEventArgs args)
{
base.OnHandlerChangingCore(args);

if (Application.Current == null)
return;

if (args.NewHandler == null || args.OldHandler is not null)
Application.Current.RequestedThemeChanged -= OnRequestedThemeChanged;
if (args.NewHandler != null && args.OldHandler == null)
Application.Current.RequestedThemeChanged += OnRequestedThemeChanged;
}

private void OnRequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
{
OnPropertyChanged(nameof(PlaceholderColor));
OnPropertyChanged(nameof(TextColor));
OnPropertyChanged(nameof(CancelButtonColor));
}

ICommand ICommandElement.Command => SearchCommand;

object ICommandElement.CommandParameter => SearchCommandParameter;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue30601.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 30601, "[Android] SearchBar does not update colors on theme change", PlatformAffected.Android)]
public class Issue30601 : ContentPage
{
public Issue30601()
{
var searchBar3 = new SearchBar
{
Placeholder = "Placeholder with AppThemeBinding - red/green"
};
searchBar3.SetAppThemeColor(SearchBar.PlaceholderColorProperty, Colors.Red, Colors.Green);
this.SetAppThemeColor(BackgroundProperty, Colors.White, Colors.Black);

Content = new StackLayout
{
Children =
{
new SearchBar
{
Placeholder = "Placeholder - system's default"
},
new SearchBar
{
PlaceholderColor = Colors.Red,
Placeholder = "Placeholder - red"
},
searchBar3,
new Button
{
Text = "Change Theme",
AutomationId = "changeThemeButton",
Command= new Command(() =>
{
Application.Current!.UserAppTheme = Application.Current!.UserAppTheme != AppTheme.Dark ? AppTheme.Dark : AppTheme.Light;
})
}
}
};
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue30601 : _IssuesUITest
{
public Issue30601(TestDevice testDevice) : base(testDevice) { }

public override string Issue => "[Android] SearchBar does not update colors on theme change";

[Test]
[Category(UITestCategories.SearchBar)]
public void SearchbarColorsShouldUpdate()
{
App.WaitForElement("changeThemeButton");
App.Tap("changeThemeButton");
VerifyScreenshot();
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public static void MapCharacterSpacing(ISearchBarHandler handler, ISearchBar sea
public static void MapTextColor(ISearchBarHandler handler, ISearchBar searchBar)
{
handler.QueryEditor?.UpdateTextColor(searchBar);
handler.PlatformView?.UpdateTextColor(searchBar);
}

public static void MapIsTextPredictionEnabled(ISearchBarHandler handler, ISearchBar searchBar)
Expand Down
70 changes: 56 additions & 14 deletions src/Core/src/Platform/Android/SearchViewExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using Android.Content.Res;
using System;
using Android.Content.Res;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Text;
using Android.Util;
using Android.Widget;
using static Android.Content.Res.Resources;
using SearchView = AndroidX.AppCompat.Widget.SearchView;

namespace Microsoft.Maui.Platform
Expand All @@ -21,22 +26,36 @@ public static void UpdatePlaceholderColor(this SearchView searchView, ISearchBar
{
editText ??= searchView.GetFirstChildOfType<EditText>();

if (editText == null)
if (editText is null)
return;

var placeholderTextColor = searchBar.PlaceholderColor;

if (placeholderTextColor == null)
{
editText.SetHintTextColor(defaultPlaceholderColor);
}
else
if (searchBar?.PlaceholderColor is Graphics.Color placeholderTextColor)
{
if (PlatformInterop.CreateEditTextColorStateList(editText.HintTextColors, placeholderTextColor.ToPlatform()) is ColorStateList c)
{
editText.SetHintTextColor(c);
}
}
else if (TryGetDefaultStateColor(searchView, Android.Resource.Attribute.TextColorHint, out var color))
{
editText.SetHintTextColor(color);

var searchMagIconImage = searchView.FindViewById<ImageView>(Resource.Id.search_mag_icon);
searchMagIconImage?.Drawable?.SetTint(color);
}
}

internal static void UpdateTextColor(this SearchView searchView, ITextStyle entry)
{
if (TryGetDefaultStateColor(searchView, Android.Resource.Attribute.TextColorPrimary, out var color) &&
searchView.GetFirstChildOfType<EditText>() is EditText editText)
{
if (entry.TextColor is null)
editText.SetTextColor(color);

var searchMagIconImage = searchView.FindViewById<ImageView>(Resource.Id.search_mag_icon);
searchMagIconImage?.Drawable?.SetTint(color);
}
}

public static void UpdateFont(this SearchView searchView, ISearchBar searchBar, IFontManager fontManager, EditText? editText = null)
Expand Down Expand Up @@ -108,12 +127,12 @@ public static void UpdateCancelButtonColor(this SearchView searchView, ISearchBa
{
var image = searchView.FindViewById<ImageView>(searchCloseButtonIdentifier);

if (image != null && image.Drawable != null)
if (image is not null && image.Drawable is Drawable drawable)
{
if (searchBar.CancelButtonColor != null)
image.Drawable.SetColorFilter(searchBar.CancelButtonColor, FilterMode.SrcIn);
else
image.Drawable.ClearColorFilter();
if (searchBar.CancelButtonColor is not null)
drawable.SetColorFilter(searchBar.CancelButtonColor, FilterMode.SrcIn);
else if (TryGetDefaultStateColor(searchView, Android.Resource.Attribute.TextColorPrimary, out var color))
drawable.SetColorFilter(color, FilterMode.SrcIn);
}
}
}
Expand Down Expand Up @@ -171,5 +190,28 @@ internal static void SetInputType(this SearchView searchView, ISearchBar searchB

editText.SetInputType(searchBar);
}

static bool TryGetDefaultStateColor(SearchView searchView, int attribute, out Color color)
{
color = default;

if (!OperatingSystem.IsAndroidVersionAtLeast(23))
return false;

if (searchView.Context?.Theme is not Theme theme)
return false;

int[] s_disabledState = [-Android.Resource.Attribute.StateEnabled];
int[] s_enabledState = [Android.Resource.Attribute.StateEnabled];

using var ta = theme.ObtainStyledAttributes([attribute]);
var cs = ta.GetColorStateList(0);
if (cs is null)
return false;

var state = searchView.Enabled ? s_enabledState : s_disabledState;
color = new Color(cs.GetColorForState(state, Color.Black));
return true;
}
}
}
Loading