From ea30e32e0a0c63fe145b000985fede64c1212895 Mon Sep 17 00:00:00 2001 From: Hudney <33006894+Hudney@users.noreply.github.com> Date: Thu, 2 Sep 2021 13:54:20 -0300 Subject: [PATCH] fix: fixes TextBox cursor color for Android 29+ Addresses #6240 --- .../Controls/TextBox/TextBoxView.Android.cs | 94 +++++++++++-------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.Android.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.Android.cs index 2fea0c762fba..16b3390100cf 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.Android.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.Android.cs @@ -136,8 +136,11 @@ private static void PrepareFields(Context? context) } var editText = new EditText(context); - _cursorDrawableResField = textViewClass.GetDeclaredField("mCursorDrawableRes"); - _cursorDrawableResField.Accessible = true; + if ((int)Build.VERSION.SdkInt < 29) + { + _cursorDrawableResField = textViewClass.GetDeclaredField("mCursorDrawableRes"); + _cursorDrawableResField.Accessible = true; + } _editorField = textViewClass.GetDeclaredField("mEditor"); _editorField.Accessible = true; @@ -146,11 +149,12 @@ private static void PrepareFields(Context? context) { _cursorDrawableField = _editorField.Get(editText)?.Class.GetDeclaredField("mCursorDrawable"); } - else + else if ((int)Build.VERSION.SdkInt == 28) { - // set differently in Android P (API 28) and higher + // set differently in Android P (API 28) _cursorDrawableField = _editorField.Get(editText)?.Class.GetDeclaredField("mDrawableForCursor"); } + // Android versions 29+ are handled directly through SetColorFilter API if (_cursorDrawableField != null) { @@ -167,51 +171,67 @@ public static void SetCursorColor(EditText editText, Color color) PrepareFields(editText.Context); } - if (_cursorDrawableField == null || _cursorDrawableResField == null || _editorField == null || PorterDuff.Mode.SrcIn == null) + if (PorterDuff.Mode.SrcIn == null) { - // PrepareFields() failed, give up now editText.Log().WarnIfEnabled(() => "Failed to change the cursor color. Some devices don't support this."); return; } - var mCursorDrawableRes = _cursorDrawableResField.GetInt(editText); - var editor = _editorField.Get(editText); - -#if __ANDROID_28__ -#pragma warning disable 618 // SetColorFilter is deprecated - if ((int)Build.VERSION.SdkInt < 28) // 28 means BuildVersionCodes.P + if ((int)Build.VERSION.SdkInt >= 29) { - var drawables = new Drawable[2]; - drawables[0] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); - drawables[1] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); - drawables[0].SetColorFilter(color, PorterDuff.Mode.SrcIn); - drawables[1].SetColorFilter(color, PorterDuff.Mode.SrcIn); - _cursorDrawableField.Set(editor, drawables); + var drawable = editText.TextCursorDrawable; + if (BlendMode.SrcAtop != null) + { + drawable?.SetColorFilter(new BlendModeColorFilter(color, BlendMode.SrcAtop)); + } } - else - { - var drawable = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); - drawable.SetColorFilter(color, PorterDuff.Mode.SrcIn); - _cursorDrawableField.Set(editor, drawable); - } -#pragma warning restore 618 // SetColorFilter is deprecated -#else - if ((int)Build.VERSION.SdkInt < 28) // 28 means BuildVersionCodes.P + else if (_cursorDrawableField == null || _cursorDrawableResField == null || _editorField == null || PorterDuff.Mode.SrcIn == null) { - var drawables = new Drawable[2]; - drawables[0] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); - drawables[1] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); - drawables[0].SetColorFilter(new BlendModeColorFilterCompat(color, BlendModeCompat.SrcIn)); - drawables[1].SetColorFilter(new BlendModeColorFilterCompat(color, BlendModeCompat.SrcIn)); - _cursorDrawableField.Set(editor, drawables); + // PrepareFields() failed, give up now + editText.Log().WarnIfEnabled(() => "Failed to change the cursor color. Some devices don't support this."); + return; } else { - var drawable = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); - drawable.SetColorFilter(new BlendModeColorFilterCompat(color, BlendModeCompat.SrcIn)); - _cursorDrawableField.Set(editor, drawable); - } + var mCursorDrawableRes = _cursorDrawableResField.GetInt(editText); + var editor = _editorField.Get(editText); + +#if __ANDROID_28__ +#pragma warning disable 618 // SetColorFilter is deprecated + if ((int)Build.VERSION.SdkInt < 28) // 28 means BuildVersionCodes.P + { + var drawables = new Drawable[2]; + drawables[0] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); + drawables[1] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); + drawables[0].SetColorFilter(color, PorterDuff.Mode.SrcIn); + drawables[1].SetColorFilter(color, PorterDuff.Mode.SrcIn); + _cursorDrawableField.Set(editor, drawables); + } + else + { + var drawable = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); + drawable.SetColorFilter(color, PorterDuff.Mode.SrcIn); + _cursorDrawableField.Set(editor, drawable); + } +#pragma warning restore 618 // SetColorFilter is deprecated +#else + if ((int)Build.VERSION.SdkInt < 28) // 28 means BuildVersionCodes.P + { + var drawables = new Drawable[2]; + drawables[0] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); + drawables[1] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); + drawables[0].SetColorFilter(new BlendModeColorFilterCompat(color, BlendModeCompat.SrcIn)); + drawables[1].SetColorFilter(new BlendModeColorFilterCompat(color, BlendModeCompat.SrcIn)); + _cursorDrawableField.Set(editor, drawables); + } + else + { + var drawable = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes); + drawable.SetColorFilter(new BlendModeColorFilterCompat(color, BlendModeCompat.SrcIn)); + _cursorDrawableField.Set(editor, drawable); + } #endif + } } catch (Exception) {