Search code examples
javaandroidreflectionandroid-edittexttextview

Setting EditText Cursor Color With Reflection Method


I've been using a reflection method to set my EditText's cursor colors programmatically which I found from this answer (I also tried this answer). However, after some recent updates, can't remember exactly when, that method no longer works, I assume that Android has probably changed something in the TextView class. Anyways, can someone help me with this? Are there now new field names for mCursorDrawableRes and mCursorDrawable, or is that whole method invalid and needs to be implemented another way now?

Update: I just found out that this method stopped working only on Android P, on the previous versions, it still works.

Update 2: I solved problem myself, check the answer if you are stuck as well.


Solution

  • OK, after digging into the Android Pie Source Code, I found out that Google has changed mCursorDrawable to mDrawableForCursor, and also changed its type from a two element Drawable array to simply Drawable, so I made some changes based on the original reflection method, and now it works for Android P:

    public static void setEditTextCursorColor(EditText editText, int color) {
        try {
            // Get the cursor resource id
            Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
            field.setAccessible(true);
            int drawableResId = field.getInt(editText);
    
            // Get the editor
            field = TextView.class.getDeclaredField("mEditor");
            field.setAccessible(true);
            Object editor = field.get(editText);
    
            // Get the drawable and set a color filter
            Drawable drawable = ContextCompat.getDrawable(editText.getContext(), drawableResId);
            drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
    
            // Set the drawables
            if(Build.VERSION.SDK_INT >= 28){//set differently in Android P (API 28)
                field = editor.getClass().getDeclaredField("mDrawableForCursor");
                field.setAccessible(true);
                field.set(editor, drawable);
            }else {
                Drawable[] drawables = {drawable, drawable};
                field = editor.getClass().getDeclaredField("mCursorDrawable");
                field.setAccessible(true);
                field.set(editor, drawables);
            }
    
            //optionally set the "selection handle" color too
            setEditTextHandleColor(editText, color);
        } catch (Exception ignored) {}
    }
    

    Side note, I really wish Google could just add a public method like setCursorDrawable() or something like that, that would've been much easier.