Search code examples
androidandroid-edittextandroid-view

Custom cursor drawable for EditText is ignored on API Q+


I want to set custom drawable as cursor for EditText.

For API < Android Q I'm using reflection and it works like intended. Starting from Android Q we have convenient method setTextCursorDrawable(@Nullable Drawable textCursorDrawable). I use it like following:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
   textCursorDrawable = ContextCompat.getDrawable(context,R.drawable.drawable_cursor)!!.tintDrawable(color)
}

Where tintDrawable method is:

private fun Drawable.tintDrawable(@ColorInt color: Int): Drawable {
   return when (this) {
      is VectorDrawableCompat -> this.apply { setTintList(ColorStateList.valueOf(color)) }
      is VectorDrawable -> this.apply { setTintList(ColorStateList.valueOf(color)) }
      else -> {
         val wrappedDrawable = DrawableCompat.wrap(this)
         DrawableCompat.setTint(wrappedDrawable, color)
         DrawableCompat.unwrap(wrappedDrawable)
      }
   }
}

and R.drawable.drawable_cursor is just simple rectangle shape:

<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <size android:width="2dp" />
    <solid android:color="?android:textColorPrimary"  />
</shape>

BUT there is no visible effect at all. Even without applying tint cursor drawable just stays the same.

There is mention in documentation that

Note that any change applied to the cursor Drawable will not be visible until the cursor is hidden and then drawn again.

So I thought I need to manually hide cursor and make it visible via setCursorVisible method but still no effect.

Does anyone have some ideas what I'm doing wrong?


Solution

  • After further investigation I discovered that setTextCursorDrawable(@Nullable Drawable textCursorDrawable) works only once per instance of EditText. So if you changed textCursorDrawable to your custom one once then you cannot change it to another, it just ignores any changes you want to make.

    My screen has default state so during screen initialisation setTextCursorDrawable changed cursor drawable for the first time but I didn't noticed that.

    So be aware of bug(or expected behaviour maybe?) that you cannot change cursor drawable multiple times per one instance of EditText.