How to change color of the bubble (under cursor) on EditText (programmatically)?

前端 未结 3 1941
执念已碎
执念已碎 2020-12-16 12:30

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 th

相关标签:
3条回答
  • 2020-12-16 12:41

    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.

    0 讨论(0)
  • 2020-12-16 12:50

    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.

    0 讨论(0)
  • 2020-12-16 12:56

    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;

    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();
      }
    }
    
    0 讨论(0)
提交回复
热议问题