使用反射方法设置EditText光标颜色
Setting EditText Cursor Color With Reflection Method
我一直在使用反射方法以编程方式设置我的 EditText
的光标颜色,这是我从这个 answer (I also tried this answer) 中找到的。然而,在最近的一些更新之后,记不清具体是什么时候,那个方法不再有效了,我假设 Android 可能改变了 TextView
class 中的某些东西。无论如何,有人可以帮我吗? mCursorDrawableRes
和 mCursorDrawable
现在是否有新的字段名称,或者整个方法是否无效并且现在需要以其他方式实施?
更新:我刚刚发现这个方法只在AndroidP上失效了,在以前的版本上,它仍然有效。
更新2:我自己解决了问题,如果你也卡住了,请查看答案。
好的,在深入研究 Android Pie 源代码后,我发现 Google 已将 mCursorDrawable
更改为 mDrawableForCursor
,并将其类型从 a 更改为二元Drawable
数组改为Drawable
,所以我在原来反射法的基础上做了一些改动,现在对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) {}
}
旁注,我真的希望 Google 可以添加一个 public 方法,如 setCursorDrawable() 或类似的方法,那样会容易得多。
不幸的是,Google 没有公开 xml 属性来着色,或设置方法,即使在兼容性库中也没有这些可绘制对象,因此目前动态设置它们的唯一方法是通过所描述的反射。
但是,您可以在 xml 中设置可绘制对象,如果您只想为现有的 material 设计可绘制对象着色,这可以通过为文本 xml 着色来完成 select handles as they are bitmap drawables,但游标drawable是一个inset drawable,所以必须从源代码重新创建。
使用的绘图是:
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 像这样处理可绘制对象:
<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
瞧,自定义彩色光标和 select 句柄与默认 material 设计版本完全匹配,避免了反射,因此不会导致警告或错误。
我一直在使用反射方法以编程方式设置我的 EditText
的光标颜色,这是我从这个 answer (I also tried this answer) 中找到的。然而,在最近的一些更新之后,记不清具体是什么时候,那个方法不再有效了,我假设 Android 可能改变了 TextView
class 中的某些东西。无论如何,有人可以帮我吗? mCursorDrawableRes
和 mCursorDrawable
现在是否有新的字段名称,或者整个方法是否无效并且现在需要以其他方式实施?
更新:我刚刚发现这个方法只在AndroidP上失效了,在以前的版本上,它仍然有效。
更新2:我自己解决了问题,如果你也卡住了,请查看答案。
好的,在深入研究 Android Pie 源代码后,我发现 Google 已将 mCursorDrawable
更改为 mDrawableForCursor
,并将其类型从 a 更改为二元Drawable
数组改为Drawable
,所以我在原来反射法的基础上做了一些改动,现在对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) {}
}
旁注,我真的希望 Google 可以添加一个 public 方法,如 setCursorDrawable() 或类似的方法,那样会容易得多。
不幸的是,Google 没有公开 xml 属性来着色,或设置方法,即使在兼容性库中也没有这些可绘制对象,因此目前动态设置它们的唯一方法是通过所描述的反射。
但是,您可以在 xml 中设置可绘制对象,如果您只想为现有的 material 设计可绘制对象着色,这可以通过为文本 xml 着色来完成 select handles as they are bitmap drawables,但游标drawable是一个inset drawable,所以必须从源代码重新创建。
使用的绘图是:
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 像这样处理可绘制对象:
<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
瞧,自定义彩色光标和 select 句柄与默认 material 设计版本完全匹配,避免了反射,因此不会导致警告或错误。