Set Textcursordrawable Programmatically

set textCursorDrawable programmatically

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) {
}
}

How to Change programmatically Edittext Cursor Color in android?

Using some reflection did the trick for me

Java:

// 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);

XML:

<?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>

Here is a method that you can use that doesn't need an XML:

public static void setCursorColor(EditText view, @ColorInt int color) {
try {
// Get the cursor resource id
Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
field.setAccessible(true);
int drawableResId = field.getInt(view);

// Get the editor
field = TextView.class.getDeclaredField("mEditor");
field.setAccessible(true);
Object editor = field.get(view);

// Get the drawable and set a color filter
Drawable drawable = ContextCompat.getDrawable(view.getContext(), drawableResId);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
Drawable[] drawables = {drawable, drawable};

// Set the drawables
field = editor.getClass().getDeclaredField("mCursorDrawable");
field.setAccessible(true);
field.set(editor, drawables);
} catch (Exception ignored) {
}
}

Set EditText cursor color

Setting the android:textCursorDrawable attribute to @null should result in the use of android:textColor as the cursor color.

Attribute "textCursorDrawable" is available in API level 12 and higher

change edittext cursor color

In your EditText properties, there is an attribute android:textCursorDrawable

Now set it to @null like,

android:textCursorDrawable="@null"

So now your EditText Cursor is same as your EditText TextColor.

Reference From Set EditText cursor color

Setting EditText Cursor Color With Reflection Method

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.

How to get height of default cursor drawable?

Using reflection i could find the height of Cursor. It has worked for Samsung edge s7. It will probably work for all devices, if the manufacturer did not make any changes to mCursorDrawableRes.

public int getHeightofCursor(Context context, EditText editText) throws Exception {
Field cursor = TextView.class.getDeclaredField("mCursorDrawableRes");
cursor.setAccessible(true);
int resid = cursor.getInt(editText);
Drawable cursorDrawable = context.getResources().getDrawable(resid);
return cursorDrawable.getIntrinsicHeight();
}

Set Entry Cursor visibility // color

You can use a custom Entry:

CustomEntry

internal class CustomEntry : EntryHandler
{
public CustomEntry()
{
}

protected override void ConnectHandler(AppCompatEditText platformView)
{
base.ConnectHandler(platformView);
platformView.ShowSoftInputOnFocus = false;
//platformView.SetCursorVisible(false); //not sure why it is not working

//replaced by this approah:
#if ANDROID29_0_OR_GREATER
platformView.SetTextCursorDrawable(Resource.Drawable.invisible_cursor);
#else
//code to handle it for API< 29, check link in edit section of my answer
#endif
}
}

MauiProgram.cs

#if ANDROID
builder.ConfigureMauiHandlers((handlers) =>
{
handlers.AddHandler(typeof(Entry), typeof(CustomEntry));
}
#endif

invisible_cursor.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent"></solid>
</shape>

EDIT

SetTextCursorDrawable() was introduced in API29+, to support earlier Android version I invite you to take a look at set textCursorDrawable programmatically, you can handdle that case in the #else of #if ANDROID29_0_OR_GREATER (code above edited).



Related Topics



Leave a reply



Submit