我一直在使用反射方法以编程方式设置answer中我的EditText
的光标颜色(我也尝试过此answer)。但是,在进行了一些最近的更新后,不记得确切的时间了,该方法不再起作用,我认为Android可能已经更改了TextView
类中的某些内容。无论如何,有人可以帮我吗?现在是否有mCursorDrawableRes
和mCursorDrawable
的新字段名称,还是整个方法无效,并且现在需要以另一种方式实现?
更新:我刚刚发现此方法仅在Android P上停止工作,在以前的版本上仍然有效。
更新2:我自己解决了问题,请检查答案是否也卡住了。
答案 0 :(得分:4)
好的,在深入研究Android Pie源代码之后,我发现Google已将mCursorDrawable
更改为mDrawableForCursor
,并将其类型从两个元素的Drawable
数组更改为简单Drawable
,所以我根据原始的反射方法进行了一些更改,现在它适用于Android P:
public static void setEditTextCursorColor(EditText editText, int color) {
try {
// Get the cursor resource id
if(Build.VERSION.SDK_INT >= 28){//set differently in Android P (API 28)
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
field = editor.getClass().getDeclaredField("mDrawableForCursor");
field.setAccessible(true);
field.set(editor, drawable);
}else {
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);
Drawable[] drawables = {drawable, drawable};
// Set the drawables
field = editor.getClass().getDeclaredField("mCursorDrawable");
field.setAccessible(true);
field.set(editor, drawables);
}
setEditTextHandleColor(editText, color);
} catch (Exception ignored) {
}
}
旁注,我真的希望Google可以添加诸如setCursorDrawable()之类的公共方法或类似的方法,这会容易得多。
答案 1 :(得分:1)
不幸的是,即使在兼容性库中,Google都没有将xml属性公开给着色或设置这些方法的可绘制对象的方法,因此,当前动态设置它们的唯一方法是通过反射进行设置。
但是,您可以在xml中设置可绘制对象,如果您只想着色现有的材质设计可绘制对象,则可以通过为文本选择手柄着色xml来完成,因为它们是位图可绘制对象,但是光标可绘制对象是一个插图可绘制的,因此必须从源代码中重新创建。
使用的可绘制对象为:
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
您可以像这样创建文本选择柄可绘制对象的着色版本:
<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
和瞧,自定义颜色的光标,并选择与默认材质设计版本完全匹配的手柄,避免反射,因此不会引起警告或错误。