代码之家  ›  专栏  ›  技术社区  ›  Jack

用反射法设置文本光标颜色

  •  1
  • Jack  · 技术社区  · 6 年前

    EditText 的光标以编程方式显示颜色 answer (我也试过这个 answer TextView 班级。不管怎样,有人能帮我吗?现在有新的字段名吗 mCursorDrawableRes mCursorDrawable ,或者整个方法是无效的,现在需要以另一种方式实现吗?

    更新:我刚刚发现这个方法只在Android P上停止工作,在以前的版本上,它仍然有效。

    更新2:我自己解决了问题,如果你也卡住了,请检查答案。

    2 回复  |  直到 6 年前
        1
  •  6
  •   Jack    5 年前

    好吧,在深入研究Android派源代码之后,我发现Google已经改变了 mCursorDrawable mDrawableForCursor ,并将其类型从双元素更改为 Drawable 可拉伸的

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

    顺便说一句,我真的希望Google可以添加一个公共方法,比如setCursorDrawable()或者类似的东西,那样会容易得多。

        2
  •  1
  •   English Dave    6 年前

    不幸的是,即使在兼容库中,Google也没有将xml属性公开给tint,也没有为这些属性设置drawables的方法,因此目前动态设置它们的唯一方法是通过所描述的反射。

    所使用的抽屉有:

    R.drawable.abc_text_select_handle_left_mtrl_light
    R.drawable.abc_text_select_handle_middle_mtrl_light
    R.drawable.abc_text_select_handle_right_mtrl_light
    R.drawable.abc_text_cursor_material
    

    您可以创建文本select handle drawables的着色版本,如下所示:

    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
        android:src="@drawable/abc_text_select_handle_left_mtrl_light"
        android:tint="@color/my_text_select_handle_color" />
    
    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
        android:src="@drawable/abc_text_select_handle_middle_mtrl_light"
        android:tint="@color/my_text_select_handle_color" />
    
    <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
        android:src="@drawable/abc_text_select_handle_right_mtrl_light"
        android:tint="@color/my_text_select_handle_color" />
    

    <inset xmlns:android="http://schemas.android.com/apk/res/android"
           android:inset="2dp">
      <shape
          android:tint="@color/my_text_cursor_color"
          android:shape="rectangle">
        <size
            android:height="2dp"
            android:width="2dp" />
        <solid
            android:color="@color/white" />
      </shape>
    </inset>
    

    将它们放置在drawables文件夹中,并在AppCompatEditText xml定义中引用它们,使用:

    android:textCursorDrawable
    android:textSelectHandle
    android:textSelectHandleLeft
    android:textSelectHandleRight