B4A Class Edittext Cursor Color

There weren't any simple way to change EditText cursor color programmatically, so here it is.
Should work with API level 15 and newer.

B4X:
Private Sub Class_Globals
    Private jo As JavaObject
End Sub

'Support for Android 4.0.x
'stackoverflow.com/questions/25996032/how-to-change-programmatically-edittext-cursor-color-in-android
Public Sub Initialize
    jo = Me
End Sub

Public Sub SetColor (EditText As EditText, Color As Int)
    jo.RunMethod("setCursorColor", Array(EditText,Color))
End Sub

#If Java
import android.widget.EditText;
import android.widget.TextView;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import java.lang.reflect.Field;
import android.support.v4.content.ContextCompat;
import android.graphics.PorterDuff;
import android.os.Build;

public void setCursorColor(EditText editText, @ColorInt int color) {
    try {
        Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
        field.setAccessible(true);
        int drawableResId = field.getInt(editText);

        Drawable drawable = ContextCompat.getDrawable(editText.getContext(), drawableResId);
        drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
        Drawable[] drawables = {drawable, drawable};

        if (Build.VERSION.SDK_INT == 15) {
            Class<?> drawableFieldClass = TextView.class;
            field = drawableFieldClass.getDeclaredField("mCursorDrawable");
            field.setAccessible(true);
            field.set(editText, drawables);

        } else {
            field = TextView.class.getDeclaredField("mEditor");
            field.setAccessible(true);
            Object editor = field.get(editText);
            field = editor.getClass().getDeclaredField("mCursorDrawable");
            field.setAccessible(true);
            field.set(editor, drawables);
        }
    } catch (Exception e) {
        
    }
}

#End If
 

Attachments

  • CursorColor.bas
    1.9 KB · Views: 289

Mike1970

Well-Known Member
Licensed User
Longtime User
I got this error:


B4X:
javac 1.8.0_221
src\barbone\LiveBadge\cursorcolor.java:6: error: package androidx.support does not exist
import androidx.support.annotation;
                       ^
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Change the java code to:
B4X:
#If Java
import android.widget.EditText;
import android.widget.TextView;
import android.graphics.drawable.Drawable;
import androidx.annotation.ColorInt;
import java.lang.reflect.Field;
import androidx.core.content.ContextCompat;
import android.graphics.PorterDuff;
import android.os.Build;

public void setCursorColor(EditText editText, @ColorInt int color) {
    try {
        Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
        field.setAccessible(true);
        int drawableResId = field.getInt(editText);

        Drawable drawable = ContextCompat.getDrawable(editText.getContext(), drawableResId);
        drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
        Drawable[] drawables = {drawable, drawable};

        if (Build.VERSION.SDK_INT == 15) {
            Class<?> drawableFieldClass = TextView.class;
            field = drawableFieldClass.getDeclaredField("mCursorDrawable");
            field.setAccessible(true);
            field.set(editText, drawables);

        } else {
            field = TextView.class.getDeclaredField("mEditor");
            field.setAccessible(true);
            Object editor = field.get(editText);
            field = editor.getClass().getDeclaredField("mCursorDrawable");
            field.setAccessible(true);
            field.set(editor, drawables);
        }
    } catch (Exception e) {
       
    }
}

#End If

And add to main module:
B4X:
#AdditionalJar: com.android.support:support-v4

This code is based on non-public APIs. I'm not sure that it will work on all Android versions.
 

Mike1970

Well-Known Member
Licensed User
Longtime User
Change the java code to:
B4X:
#If Java
import android.widget.EditText;
import android.widget.TextView;
import android.graphics.drawable.Drawable;
import androidx.annotation.ColorInt;
import java.lang.reflect.Field;
import androidx.core.content.ContextCompat;
import android.graphics.PorterDuff;
import android.os.Build;

public void setCursorColor(EditText editText, @ColorInt int color) {
    try {
        Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
        field.setAccessible(true);
        int drawableResId = field.getInt(editText);

        Drawable drawable = ContextCompat.getDrawable(editText.getContext(), drawableResId);
        drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
        Drawable[] drawables = {drawable, drawable};

        if (Build.VERSION.SDK_INT == 15) {
            Class<?> drawableFieldClass = TextView.class;
            field = drawableFieldClass.getDeclaredField("mCursorDrawable");
            field.setAccessible(true);
            field.set(editText, drawables);

        } else {
            field = TextView.class.getDeclaredField("mEditor");
            field.setAccessible(true);
            Object editor = field.get(editText);
            field = editor.getClass().getDeclaredField("mCursorDrawable");
            field.setAccessible(true);
            field.set(editor, drawables);
        }
    } catch (Exception e) {
      
    }
}

#End If

And add to main module:
B4X:
#AdditionalJar: com.android.support:support-v4

This code is based on non-public APIs. I'm not sure that it will work on all Android versions.
Nope, it didn't work to me. Thanks anyway!
I will find another method. Maybe :'D
 

npsonic

Active Member
Licensed User
Nope, it didn't work to me. Thanks anyway!
I will find another method. Maybe :'D
I made some changes and it should now work also with the newer APIs.
Give it a try and report here how it goes.

B4X:
Private Sub Class_Globals
    Private jo As JavaObject
End Sub

'Support for Android 4.0.x
'stackoverflow.com/questions/25996032/how-to-change-programmatically-edittext-cursor-color-in-android
Public Sub Initialize
    jo = Me
End Sub

Public Sub SetColor (EditText As EditText, Color As Int)
    jo.RunMethod("setCursorColor", Array(EditText,Color))
End Sub

#If Java
import android.widget.EditText;
import android.widget.TextView;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import java.lang.reflect.Field;
import android.support.v4.content.ContextCompat;
import android.graphics.PorterDuff;
import android.os.Build;

public void setCursorColor(EditText editText, @ColorInt int color) {
    try {
        Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
        field.setAccessible(true);
        int drawableResId = field.getInt(editText);

        Drawable drawable = ContextCompat.getDrawable(editText.getContext(), drawableResId);
        drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);    

        if (Build.VERSION.SDK_INT == 15) {
            Drawable[] drawables = {drawable, drawable};
         
            Class<?> drawableFieldClass = TextView.class;
            field = drawableFieldClass.getDeclaredField("mCursorDrawable");
            field.setAccessible(true);        
            field.set(editText, drawables);

        } else if (Build.VERSION.SDK_INT >= 28) {
            field = TextView.class.getDeclaredField("mEditor");
            field.setAccessible(true);
            Object editor = field.get(editText);
         
            field = editor.getClass().getDeclaredField("mDrawableForCursor");
            field.setAccessible(true);
            field.set(editor, drawable);
         
        } else {
            Drawable[] drawables = {drawable, drawable};
         
            field = TextView.class.getDeclaredField("mEditor");
            field.setAccessible(true);
            Object editor = field.get(editText);
         
            field = editor.getClass().getDeclaredField("mCursorDrawable");
            field.setAccessible(true);
            field.set(editor, drawables);
        }
    } catch (Exception e) {    
    }
}

#End If

Also congratulations, you got me back here after 4 months away from this forum.
 

Attachments

  • CursorColor.bas
    2.3 KB · Views: 252

Mike1970

Well-Known Member
Licensed User
Longtime User
Give it a try and report here how it goes
So, before i start. Thanks for your support.
I tried the new class, but it is still not working.

I put this code after the loadlayout (take a look if it is correct):

B4X:
Dim curcol As CursorColor
curcol.Initialize
curcol.SetColor(edtNome, Colors.Red)

In the begininng it gave me an error realtive to the imported library in the java code (The same of my first post), i replaced all the import with the ones that gave Erel in the precedent post and then it compiled successfully.
But the cursor color is still android green.



Also congratulations, you got me back here after 4 months away from this forum.
Congrats to your patience and work
 

npsonic

Active Member
Licensed User
So, before i start. Thanks for your support.
I tried the new class, but it is still not working.

I put this code after the loadlayout (take a look if it is correct):

B4X:
Dim curcol As CursorColor
curcol.Initialize
curcol.SetColor(edtNome, Colors.Red)

In the begininng it gave me an error realtive to the imported library in the java code (The same of my first post), i replaced all the import with the ones that gave Erel in the precedent post and then it compiled successfully.
But the cursor color is still android green.




Congrats to your patience and work

Does this simple example work or fail? There is possibility that device you are using doesn't support that specific method as it's non public like Erel wrote.

B4X:
#Region  Project Attributes
    #ApplicationLabel: Example
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#AdditionalJar: com.android.support:support-v4

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim edt As EditText : edt.Initialize("")
    Activity.AddView(edt, 16dip, 16dip, Activity.Width - 32dip, 48dip)
    Dim cc As CursorColor
    cc.Initialize
    cc.SetColor(edt, Colors.Red)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub
 

Mike1970

Well-Known Member
Licensed User
Longtime User
Does this simple example work or fail? There is possibility that device you are using doesn't support that specific method as it's non public like Erel wrote.

B4X:
#Region  Project Attributes
    #ApplicationLabel: Example
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#AdditionalJar: com.android.support:support-v4

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim edt As EditText : edt.Initialize("")
    Activity.AddView(edt, 16dip, 16dip, Activity.Width - 32dip, 48dip)
    Dim cc As CursorColor
    cc.Initialize
    cc.SetColor(edt, Colors.Red)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub
It didn't work, but later I will try to do a sample project to test it alone
 
Top