43

If I add an EditText in XML I can set textCursorDrawable="@null":

<EditText
    android:id="@+id/txtE3Casecode4"
    android:layout_width="30dp"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:background="#C7C7C5"
    android:textCursorDrawable="@null"
    android:ems="10"
    android:inputType="number"
    android:maxLength="2"
    android:text="01"
    android:textColor="#000000" />

Now I draw an EditText in Java. I want set android:textCursorDrawable="@null".

LinearLayout.LayoutParams paramtext = new LinearLayout.LayoutParams(
    LinearLayout.LayoutParams.FILL_PARENT,
    LinearLayout.LayoutParams.WRAP_CONTENT);
EditText txtOther = new EditText(this);
txtOther.setLayoutParams(paramtext);
txtOther.setBackgroundColor(Color.WHITE);
txtOther.setTextColor(Color.BLACK);
txtOther.setId(99999);
// txtOther.setCursorDrawable ?                                

How do set it?

Cœur
  • 37,241
  • 25
  • 195
  • 267
D T
  • 3,522
  • 7
  • 45
  • 89

7 Answers7

70

Update 2019: There is no public API to set the cursor drawable. See https://stackoverflow.com/a/57555148/253468 for API available on 29 and above, before that conditionally you'll need to use reflection as described below.

Before API 29 you can set it programmatically by using reflection. The field mCursorDrawableRes hasn't changed so this should work on all devices, unless a manufacturer changed something or it is later changed.

Use reflection to set the cursor:

EditText yourEditText = new EditText(context);

...

try {
    // https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/widget/TextView.java#L562-564
    Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
    f.setAccessible(true);
    f.set(yourEditText, R.drawable.cursor);
} catch (Exception ignored) {
}

Define a cursor drawable in your app:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    
    <solid android:color="#ff000000" />
    
    <size android:width="1dp" />
    
</shape>

Another approach:

You can also set the cursor color with the following method:

public static void setCursorDrawableColor(EditText editText, int color) {
    try { 
        Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
        fCursorDrawableRes.setAccessible(true);
        int mCursorDrawableRes = fCursorDrawableRes.getInt(editText);
        Field fEditor = TextView.class.getDeclaredField("mEditor");
        fEditor.setAccessible(true);
        Object editor = fEditor.get(editText);
        Class<?> clazz = editor.getClass();
        Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable");
        fCursorDrawable.setAccessible(true);
        Drawable[] drawables = new Drawable[2];
        drawables[0] = editText.getContext().getResources().getDrawable(mCursorDrawableRes);
        drawables[1] = editText.getContext().getResources().getDrawable(mCursorDrawableRes);
        drawables[0].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        drawables[1].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        fCursorDrawable.set(editor, drawables);
    } catch (Throwable ignored) {
    } 
} 
TWiStErRob
  • 44,762
  • 26
  • 170
  • 254
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
  • Works perfect, mark it as the correct answer please. – Corbella Jul 30 '15 at 11:33
  • Mark this one as answer. The use of reflection class works very well. I have tested its working. – V_J Aug 04 '15 at 07:17
  • 1
    Anything involving reflection should not be recommended, even if it does solve the problem. – Alex Fu Apr 29 '16 at 15:39
  • 1
    @AlexFu, the Android support libraries use reflection. I agree it should be avoided if possible but not disregarded. – Jared Rummler Apr 29 '16 at 15:49
  • The method using reflection does not work for some Huawei devices, because editor is of type HwEditor, you should get mCursorDrawable from the superclass. – Kamen Dobrev Nov 13 '18 at 08:26
  • For me the first and second method work initially, but when trying to update the cursor-drawable they don't work. –  Dec 12 '18 at 16:58
  • Has anyone tried to change the color of the caret on PIXEL XL phone updated to API 28? In my case the reflection cannot find the "mCursorDrawable" of the "mEditor". I found some posts online suggesting to use "mDrawableForCursor" instead, but the result is the same. Can anyone suggest approach which does not use any XML and works for all devices? – Pavel Pavlov Apr 09 '19 at 11:18
  • 2
    This will crash starting Android 10. Any non documented method access is restricted https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces – Sanmoy Aug 19 '20 at 14:05
9

Using reflection for the cursor drawable is prohibited from Android Q.

Instead, there is a new setTextCursorDrawable API and we can use this.

Hyukjae
  • 168
  • 2
  • 5
2

This work for me

 public void setCursorDrawable(@DrawableRes int resId) {
        if (mEditText == null)
            return;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            mEditText.setTextCursorDrawable(resId);
            return;
        }
        try {
            @SuppressLint("SoonBlockedPrivateApi") Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
            field.setAccessible(true);
            field.set(mEditText, resId);
        } catch (Throwable throwable) {
            Logger.e(TAG, throwable);
        }
    }
}
Notsfsssf
  • 462
  • 5
  • 14
1

the answer is ---------------------> It's unattainable.

Actually, I also met this problem in my work, but after checking google's doc and source code, I fond that you cannot set this attribute in java code.

In TextView class you can find the code below

case com.android.internal.R.styleable.TextView_textCursorDrawable:
    mCursorDrawableRes = a.getResourceId(attr, 0);
    break;

but the method textCursorDrawable() is only existed in R.attr, if you wanna set this attribute, you can only call the construct method below by including a editText in XML file.

public EditText(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.editTextStyle);
}
biegleux
  • 13,179
  • 11
  • 45
  • 52
cinsondev
  • 11
  • 3
  • http://stackoverflow.com/questions/21706567/how-can-i-prevent-the-cursor-from-resizing-in-an-edittext-multiautocompletetext - I'm looking for something similar and related – Rickster Feb 11 '14 at 17:44
0

If you use the AppCompat library and your Activity extends AppCompatActivity, you can set the color of the text cursor (for all EditTexts) using an XML style of colorAccent:

<style name="AppTheme" parent="@style/Theme.AppCompat">
    <item name="colorAccent">#FF4081</item>
</style>

This works on Android 5+ and is backwards compatible with older Android versions from Android 4.4 (API 19) to Android 4.0 (API 14). Note: If you're using an AutoCompleteTextView, ensure that any custom subclass of it extends AppCompatAutoCompleteTextView, otherwise the text cursor styling will not work.

See also this guide, for how to apply the color accent (tint) to Dialog buttons: Android v21 Theme.Appcompat color accent is ignored, no padding on dialogs

Mr-IDE
  • 7,051
  • 1
  • 53
  • 59
0

MySharedPreferences().color = Color in Hexadecimal -> #FF5733

Programmatically a method

    fun EditText.standardSimpleEditText(){
    this.apply {
        highlightColor = getColorWithAlpha(getValidateColorHex(MySharedPreferences().color), 0.2f)

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
            val drawable = ContextCompat.getDrawable(this.context, R.drawable.cursor) as Drawable
            val customDrawable = tintDrawable(drawable, MySharedPreferences().color)
            textCursorDrawable = customDrawable
        }
    }
}

Cursor.XML

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="@color/colorBlack" />
    <size android:width="1.8dp" />
</shape>

Validate color hexa

fun getValidateColorHex(color: Int = MySharedPreferences().color): Int{
    val hexColor = "#"+Integer.toHexString(color).substring(2)
    val validateColor = Color.parseColor(hexColor)
    return validateColor
}
-1

You should use TextInputLayout you are in 2020 , it's working on all devices

<com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:layout_marginTop="26dp"
        android:layout_marginEnd="30dp"
        android:theme="@style/TextInputLayoutAppearance"
        app:endIconMode="clear_text"
        app:hintEnabled="false">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/gallery_search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fontFamily="@font/inter_medium"
            android:hint="Hint here"
            android:inputType="text"
            android:cursorVisible="true"
            android:focusable="true"
            />

    </com.google.android.material.textfield.TextInputLayout>

This is main don't forget to add this, you can change the color of the cursor from here

<style name="TextInputLayoutAppearance" parent="Widget.Design.TextInputLayout">
        <item name="colorControlNormal">@color/black</item>
        <item name="colorControlActivated">@color/black</item>
        <item name="colorControlHighlight">@color/blue</item>
    </style>

For more information about TextInputLayout visit here:- https://material.io/develop/android/components/text-fields

iamkdblue
  • 3,448
  • 2
  • 25
  • 43