20

I have EditText and want to change color PROGRAMMATICALLY on code.

To change color of cursor I use this code.

But how to change color of the circle on EditView PROGRAMMATICALLY on code? orange bubble

General Grievance
  • 4,555
  • 31
  • 31
  • 45
NickUnuchek
  • 11,794
  • 12
  • 98
  • 138
  • Possible duplicate of [How to change EditText bubble color (under cursor) in android?](http://stackoverflow.com/questions/35337909/how-to-change-edittext-bubble-color-under-cursor-in-android) – Ankita Shah Nov 30 '16 at 13:21
  • @Jack Did you read question? change color programmatic on code!!! – NickUnuchek Nov 30 '16 at 13:21
  • You can create a new theme with required color set to colorAccent and set the theme programatically. – Myth Nov 30 '16 at 13:29
  • @NougatLover srly? ok... how to create theme programatically with dynamic color? – NickUnuchek Nov 30 '16 at 13:35
  • 2
    try this. http://stackoverflow.com/questions/25996032/how-to-change-programatically-edittext-cursor-color-in-android – SAM Nov 30 '16 at 13:38
  • @NickUnuchek I said, create theme in style and preset required color there, and then set that theme programatically. Anyhow, looks like, you don't want static color at all, and it should be changed programmatically whenever required. Hope I understood your question this time. – Myth Nov 30 '16 at 13:53
  • Try this for changing the cursor color programatically https://stackoverflow.com/a/26543290/5060269 – Shubham Goel Jun 01 '17 at 12:44
  • Refer below link. You might get an answer. https://stackoverflow.com/questions/25996032/how-to-change-programatically-edittext-cursor-color-in-android – Amit Thakkar Jun 05 '17 at 11:30
  • So you can set custom theme, as here https://medium.com/@werder630/android-textview-change-color-of-select-handlers-838616e9e327 – Werder Jun 15 '20 at 13:48

3 Answers3

18

You will need to use reflection to tint the select handles (bubbles). I wrote the following class this morning:

Example usage:

try {
  EditTextTint.applyColor(editText, Color.CYAN);
} catch (EditTextTint.EditTextTintError e) {
  e.printStackTrace();
}

EditTextTint.java:

import android.content.res.Resources;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.widget.EditText;
import android.widget.TextView;
import java.lang.reflect.Field;

/**
 * Tint the cursor and select handles of an {@link EditText} programmatically.
 */
public class EditTextTint {

  /**
   * Set the cursor and handle colors for an {@link EditText} programmatically.
   *
   * @param editText
   *     The {@link EditText} to tint
   * @param color
   *     The color to apply for the cursor and select handles
   * @throws EditTextTintError
   *     If an error occured while attempting to tint the view.
   */
  public static void applyColor(@NonNull EditText editText, @ColorInt int color) throws EditTextTintError {
    EditTextTint editTextTint = new Builder(editText)
        .setCursorColor(color)
        .setSelectHandleLeftColor(color)
        .setSelectHandleRightColor(color)
        .setSelectHandleMiddleColor(color)
        .build();
    editTextTint.apply();
  }

  private final EditText editText;
  private final Integer cursorColor;
  private final Integer selectHandleLeftColor;
  private final Integer selectHandleRightColor;
  private final Integer selectHandleMiddleColor;

  private EditTextTint(Builder builder) {
    editText = builder.editText;
    cursorColor = builder.cursorColor;
    selectHandleLeftColor = builder.selectHandleLeftColor;
    selectHandleRightColor = builder.selectHandleRightColor;
    selectHandleMiddleColor = builder.selectHandleMiddleColor;
  }

  /**
   * Sets the color for the cursor and handles on the {@link EditText editText}.
   *
   * @throws EditTextTintError
   *     if an error occurs while tinting the view.
   */
  public void apply() throws EditTextTintError {
    try {
      Resources res = editText.getContext().getResources();

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

      if (cursorColor != null) {
        // Get the cursor drawable, tint it, and set it on the TextView Editor
        field = TextView.class.getDeclaredField("mCursorDrawableRes");
        field.setAccessible(true);
        int cursorDrawableRes = field.getInt(editText);
        Drawable cursorDrawable = res.getDrawable(cursorDrawableRes).mutate();
        cursorDrawable.setColorFilter(cursorColor, PorterDuff.Mode.SRC_IN);
        Drawable[] drawables = {cursorDrawable, cursorDrawable};
        field = editor.getClass().getDeclaredField("mCursorDrawable");
        field.setAccessible(true);
        field.set(editor, drawables);
      }

      String[] resFieldNames = {"mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes"};
      String[] drawableFieldNames = {"mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"};
      Integer[] colors = {selectHandleLeftColor, selectHandleRightColor, selectHandleMiddleColor};

      for (int i = 0; i < resFieldNames.length; i++) {
        Integer color = colors[i];
        if (color == null) {
          continue;
        }

        String resFieldName = resFieldNames[i];
        String drawableFieldName = drawableFieldNames[i];

        field = TextView.class.getDeclaredField(resFieldName);
        field.setAccessible(true);
        int selectHandleRes = field.getInt(editText);

        Drawable selectHandleDrawable = res.getDrawable(selectHandleRes).mutate();
        selectHandleDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);

        field = editor.getClass().getDeclaredField(drawableFieldName);
        field.setAccessible(true);
        field.set(editor, selectHandleDrawable);
      }
    } catch (Exception e) {
      throw new EditTextTintError("Error applying tint to " + editText, e);
    }
  }

  public static class Builder {

    final EditText editText;
    Integer cursorColor;
    Integer selectHandleLeftColor;
    Integer selectHandleRightColor;
    Integer selectHandleMiddleColor;

    public Builder(@NonNull EditText editText) {
      this.editText = editText;
    }

    public Builder setCursorColor(@ColorInt int cursorColor) {
      this.cursorColor = cursorColor;
      return this;
    }

    public Builder setSelectHandleLeftColor(@ColorInt int selectHandleLeftColor) {
      this.selectHandleLeftColor = selectHandleLeftColor;
      return this;
    }

    public Builder setSelectHandleRightColor(@ColorInt int selectHandleRightColor) {
      this.selectHandleRightColor = selectHandleRightColor;
      return this;
    }

    public Builder setSelectHandleMiddleColor(@ColorInt int selectHandleMiddleColor) {
      this.selectHandleMiddleColor = selectHandleMiddleColor;
      return this;
    }

    public EditTextTint build() {
      return new EditTextTint(this);
    }

  }

  public static class EditTextTintError extends Exception {

    public EditTextTintError(String message, Throwable cause) {
      super(message, cause);
    }
  }

}

Note: This should work from Jelly Bean to Nougat. However, since it uses reflection to get and set private fields this may break in future releases of Android or if a manufacturer has made changes to EditText.

Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
3

The below method works for all cursors bubble such as left, right and center. I mean,beside your request, It works for both left and right ones.

For example; Beside your request, It works for both left and right ones

You can change that method to only color the center handle by removing the left and right field names in the two arrays.

public static void colorHandles(TextView view, int color) {
  try {
    Field editorField = TextView.class.getDeclaredField("mEditor");
    if (!editorField.isAccessible()) {
      editorField.setAccessible(true);
    }

    Object editor = editorField.get(view);
    Class<?> editorClass = editor.getClass();

    String[] handleNames = {"mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"};
    String[] resNames = {"mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes"};

    for (int i = 0; i < handleNames.length; i++) {
      Field handleField = editorClass.getDeclaredField(handleNames[i]);
      if (!handleField.isAccessible()) {
        handleField.setAccessible(true);
      }

      Drawable handleDrawable = (Drawable) handleField.get(editor);

      if (handleDrawable == null) {
        Field resField = TextView.class.getDeclaredField(resNames[i]);
        if (!resField.isAccessible()) {
          resField.setAccessible(true);
        }
        int resId = resField.getInt(view);
        handleDrawable = view.getResources().getDrawable(resId);
      }

      if (handleDrawable != null) {
        Drawable drawable = handleDrawable.mutate();
        drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
        handleField.set(editor, drawable);
      }
    }
  } catch (Exception e) {
    e.printStackTrace();
  }
}
ziLk
  • 3,120
  • 21
  • 45
-2

try this: change the value in values/colors.xml file

<color name="colorAccent">#263238</color>

change this color code #263238 to your own color code, so that it will be applicable to all the project. Hope this will help you.

Ram Koti
  • 2,203
  • 7
  • 26
  • 36
  • I know about styles and themes, did you read question? I want change it programmatic on code!!! – NickUnuchek Nov 30 '16 at 13:33
  • Ya you have edited your post recently, I thought you need no change the cursor color for throughout the project, so I have suggested that post, – Ram Koti Nov 30 '16 at 13:36