0

I have an application that has 4 styles, each one has a different colorAccent. Depending on the user actions, the style being used may change, and so does the colorAccent.

There's also two somewhat-static EditText views ( these view won't disappear on the app's lifecycle, since they are present in the "Home" page of the app ). For reference, let's assume that I have:

2 Views

  • EditTextA
  • EditTextB

4 Styles

  • StyleR with Red as colorAccent
  • StyleG with Green as colorAccent
  • StyleB with Blue as colorAccent
  • StyleY with Yellow as colorAccent

If I have StyleR as the current style and tap the EditTextA the cursor will immediately appear coloured red. If I change the style to StyleG, tap the EditTextA, type something and select it, I'll have a red cursor with a green pointer beneath it. Meanwhile, if I tap the EditTextB, the cursor will be green.

I've tried to Invalidate() and PostInvalidate() both views within the RunOnUiThread, but they wouldn't correct their colours.

Any other EditText that is inflated between the style changes get the correct colour.

Community
  • 1
  • 1
auhmaan
  • 726
  • 1
  • 8
  • 28

2 Answers2

0

Based on this answer by Jared Rummler, I've managed to do what I want in Xamarin. This is the code I ended up with:

public static void SetCursorColor( this EditText editText, Resources resources, Int32 colorResourceId ) {
    try {
        TextView
            textViewTemplate = new TextView( editText.Context );

        //
        // EditText Cursor
        //
        var field = textViewTemplate.Class.GetDeclaredField( "mCursorDrawableRes" );
        field.Accessible = true;
        Int32 drawableResId = field.GetInt( editText );

        field = textViewTemplate.Class.GetDeclaredField( "mEditor" );
        field.Accessible = true;
        var editor = field.Get( editText );

        Drawable drawable = resources.GetDrawable( drawableResId );
        drawable.SetColorFilter( resources.GetColor( colorResourceId ), PorterDuff.Mode.SrcIn );
        Drawable[] drawables = { drawable, drawable };

        field = editor.Class.GetDeclaredField( "mCursorDrawable" );
        field.Accessible = true;
        field.Set( editor, drawables );

        //
        // EditText Pointer
        //
        String[]
            fieldsNames = { "mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes" },
            drawablesNames = { "mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter" };

        for( Int32 index = 0; index < fieldsNames.Length && index < drawablesNames.Length; index++ ) {
            String
                fieldName = fieldsNames[ index ],
                drawableName = drawablesNames[ index ];

            field = textViewTemplate.Class.GetDeclaredField( fieldName );
            field.Accessible = true;
            Int32 handle = field.GetInt( editText );

            Drawable handleDrawable = resources.GetDrawable( handle );
            handleDrawable.SetColorFilter( resources.GetColor( colorResourceId ), PorterDuff.Mode.SrcIn );

            field = editor.Class.GetDeclaredField( drawableName );
            field.Accessible = true;
            field.Set( editor, handleDrawable );
        }
    } catch( Exception exception ) {

    }
}
auhmaan
  • 726
  • 1
  • 8
  • 28
0

I needed only white cursor and pointer for Android project, and based on "auhmaan" answer I wrote this code in Droid Renderer and it works. Perhaps it can be helpful for someone:

if (Control != null && Element != null)
{
    // set the cursor color the same as the entry TextColor
    IntPtr IntPtrtextViewClass = JNIEnv.FindClass(typeof(TextView));
    IntPtr mCursorDrawableResProperty =
    JNIEnv.GetFieldID(IntPtrtextViewClass, "mCursorDrawableRes", "I");
    // replace 0 with a Resource.Drawable.my_cursor 
    JNIEnv.SetField(Control.Handle, mCursorDrawableResProperty, 0);

    try
        {
            TextView textViewTemplate = new TextView(Control.Context);

            var field = textViewTemplate.Class.GetDeclaredField("mEditor");
            field.Accessible = true;
            var editor = field.Get(Control);

            //
            // EditText Pointer
            //
            String[]
            fieldsNames = { "mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes" },
            drawablesNames = { "mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter" };

            for (Int32 index = 0; index < fieldsNames.Length && index < drawablesNames.Length; index++)
                {
                    String
                    fieldName = fieldsNames[index],
                    drawableName = drawablesNames[index];

                    field = textViewTemplate.Class.GetDeclaredField(fieldName);
                    field.Accessible = true;
                    Int32 handle = field.GetInt(Control);

                    Drawable handleDrawable = Resources.GetDrawable(handle);

                  handleDrawable.SetColorFilter(Xamarin.Forms.Color.White.ToAndroid(), PorterDuff.Mode.SrcIn);

                    field = editor.Class.GetDeclaredField(drawableName);
                    field.Accessible = true;
                    field.Set(editor, handleDrawable);
                }
        }
        catch (Exception ex)
        {
        }
    }
Nazar Frankiv
  • 61
  • 1
  • 4