Skip to content
Merged
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
41 changes: 28 additions & 13 deletions src/Core/src/Platform/Android/SearchViewExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static void UpdatePlaceholderColor(this SearchView searchView, ISearchBar
editText.SetHintTextColor(color);

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

Expand All @@ -57,7 +57,7 @@ internal static void UpdateTextColor(this SearchView searchView, ITextStyle entr
editText.SetTextColor(color);

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

Expand Down Expand Up @@ -129,14 +129,10 @@ public static void UpdateCancelButtonColor(this SearchView searchView, ISearchBa
if (searchCloseButtonIdentifier > 0)
{
var image = searchView.FindViewById<ImageView>(searchCloseButtonIdentifier);

if (image is not null && image.Drawable is Drawable drawable)
{
if (searchBar.CancelButtonColor is not null)
drawable.SetColorFilter(searchBar.CancelButtonColor, FilterMode.SrcIn);
else if (TryGetDefaultStateColor(searchView, AAttribute.TextColorPrimary, out var color))
drawable.SetColorFilter(color, FilterMode.SrcIn);
}
if (searchBar.CancelButtonColor is not null)
SafeSetTint(image, searchBar.CancelButtonColor.ToPlatform());
else if (TryGetDefaultStateColor(searchView, AAttribute.TextColorPrimary, out var color))
SafeSetTint(image, color);
}
}

Expand All @@ -154,9 +150,9 @@ internal static void UpdateSearchIconColor(this SearchView searchView, ISearchBa
if (image?.Drawable is not null)
{
if (searchBar.SearchIconColor is not null)
image.Drawable.SetColorFilter(searchBar.SearchIconColor, FilterMode.SrcIn);
SafeSetTint(image, searchBar.SearchIconColor.ToPlatform());
else
image.Drawable.ClearColorFilter();
SafeSetTint(image, Color.Transparent);
}
}
}
Expand Down Expand Up @@ -240,5 +236,24 @@ static bool TryGetDefaultStateColor(SearchView searchView, int attribute, out Co
color = new Color(cs.GetColorForState(state, Color.Black));
return true;
}

/// <summary>
/// Safely applies tint to an ImageView's drawable by mutating it first.
/// This prevents crashes when the drawable is shared across multiple views.
/// </summary>
/// <remarks>
/// Android shares Drawable resources for memory efficiency. Modifying a shared
/// drawable without calling Mutate() first causes race conditions and crashes.
/// See: https://developer.android.com/reference/android/graphics/drawable/Drawable#mutate()
/// </remarks>
internal static void SafeSetTint(ImageView? imageView, Color color)
{
if (imageView?.Drawable is not Drawable drawable)
return;

var safe = drawable.Mutate();
safe.SetTint(color);
imageView?.SetImageDrawable(safe);
}
}
}
}
Loading