在android中我们可以通过以下方式更改光标颜色:
android:textCursorDrawable="@drawable/black_color_cursor"
。
我们如何动态地做到这一点?
在我的情况下,我将光标drawable设置为白色,但我需要更改黑色怎么办?
// Set an EditText view to get user input
final EditText input = new EditText(nyactivity);
input.setTextColor(getResources().getColor(R.color.black));
答案 0 :(得分:75)
使用一些反射为我做了诀窍
爪哇:
// https://github.com/android/platform_frameworks_base/blob/kitkat-release/core/java/android/widget/TextView.java#L562-564
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
f.setAccessible(true);
f.set(yourEditText, R.drawable.cursor);
XML:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#ff000000" />
<size android:width="1dp" />
</shape>
以下是一种不需要XML的方法:
public static void setCursorColor(EditText view, @ColorInt int color) {
try {
// Get the cursor resource id
Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
field.setAccessible(true);
int drawableResId = field.getInt(view);
// Get the editor
field = TextView.class.getDeclaredField("mEditor");
field.setAccessible(true);
Object editor = field.get(view);
// Get the drawable and set a color filter
Drawable drawable = ContextCompat.getDrawable(view.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);
} catch (Exception ignored) {
}
}
答案 1 :(得分:9)
android:textCursorDrawable="@null"
然后在申请中:
final EditText input = new EditText(nyactivity);
input.setTextColor(getResources().getColor(R.color.black));
答案 2 :(得分:7)
这是@Jared Rummler函数的重写版本,但有一些改进:
getDrawable(Context, int)
特殊getDrawable(int)
功能。private static final Field
sEditorField,
sCursorDrawableField,
sCursorDrawableResourceField;
static {
Field editorField = null;
Field cursorDrawableField = null;
Field cursorDrawableResourceField = null;
boolean exceptionThrown = false;
try {
cursorDrawableResourceField = TextView.class.getDeclaredField("mCursorDrawableRes");
cursorDrawableResourceField.setAccessible(true);
final Class<?> drawableFieldClass;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
drawableFieldClass = TextView.class;
} else {
editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
drawableFieldClass = editorField.getType();
}
cursorDrawableField = drawableFieldClass.getDeclaredField("mCursorDrawable");
cursorDrawableField.setAccessible(true);
} catch (Exception e) {
exceptionThrown = true;
}
if (exceptionThrown) {
sEditorField = null;
sCursorDrawableField = null;
sCursorDrawableResourceField = null;
} else {
sEditorField = editorField;
sCursorDrawableField = cursorDrawableField;
sCursorDrawableResourceField = cursorDrawableResourceField;
}
}
public static void setCursorColor(EditText editText, int color) {
if (sCursorDrawableField == null) {
return;
}
try {
final Drawable drawable = getDrawable(editText.getContext(),
sCursorDrawableResourceField.getInt(editText));
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
sCursorDrawableField.set(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN
? editText : sEditorField.get(editText), new Drawable[] {drawable, drawable});
} catch (Exception ignored) {
}
}
private static Drawable getDrawable(Context context, int id) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return context.getResources().getDrawable(id);
} else {
return context.getDrawable(id);
}
}
答案 3 :(得分:2)
Kotlin版本,适用于api 14到api 29
fun setCursorDrawableColor(editText: TextView, @ColorInt color: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val gradientDrawable = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(color, color))
gradientDrawable.setSize(2.spToPx(editText.context).toInt(), editText.textSize.toInt())
editText.textCursorDrawable = gradientDrawable
return
}
try {
val editorField = try {
TextView::class.java.getDeclaredField("mEditor").apply { isAccessible = true }
} catch (t: Throwable) {
null
}
val editor = editorField?.get(editText) ?: editText
val editorClass: Class<*> = if (editorField == null) TextView::class.java else editor.javaClass
val tintedCursorDrawable = TextView::class.java.getDeclaredField("mCursorDrawableRes")
.apply { isAccessible = true }
.getInt(editText)
.let { ContextCompat.getDrawable(editText.context, it) ?: return }
.let { tintDrawable(it, color) }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
editorClass
.getDeclaredField("mDrawableForCursor")
.apply { isAccessible = true }
.run { set(editor, tintedCursorDrawable) }
} else {
editorClass
.getDeclaredField("mCursorDrawable")
.apply { isAccessible = true }
.run { set(editor, arrayOf(tintedCursorDrawable, tintedCursorDrawable)) }
}
} catch (t: Throwable) {
t.printStackTrace()
}
}
fun Number.spToPx(context: Context? = null): Float {
val res = context?.resources ?: android.content.res.Resources.getSystem()
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), res.displayMetrics)
}
fun tintDrawable(drawable: Drawable, @ColorInt color: Int): Drawable {
(drawable as? VectorDrawableCompat)
?.apply { setTintList(ColorStateList.valueOf(color)) }
?.let { return it }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
(drawable as? VectorDrawable)
?.apply { setTintList(ColorStateList.valueOf(color)) }
?.let { return it }
}
val wrappedDrawable = DrawableCompat.wrap(drawable)
DrawableCompat.setTint(wrappedDrawable, color)
return DrawableCompat.unwrap(wrappedDrawable)
}
答案 4 :(得分:1)
我们设法做到了:
答案 5 :(得分:1)
受@Jared Rummler和@Oleg Barinov的启发,我精心设计了同样适用于API 15的解决方案-
public static void setCursorColor(EditText editText, @ColorInt int color) {
try {
// Get the cursor resource id
Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
field.setAccessible(true);
int drawableResId = field.getInt(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};
if (Build.VERSION.SDK_INT == 15) {
// Get the editor
Class<?> drawableFieldClass = TextView.class;
// Set the drawables
field = drawableFieldClass.getDeclaredField("mCursorDrawable");
field.setAccessible(true);
field.set(editText, drawables);
} else {
// Get the editor
field = TextView.class.getDeclaredField("mEditor");
field.setAccessible(true);
Object editor = field.get(editText);
// Set the drawables
field = editor.getClass().getDeclaredField("mCursorDrawable");
field.setAccessible(true);
field.set(editor, drawables);
}
} catch (Exception e) {
Log.e(LOG_TAG, "-> ", e);
}
}
答案 6 :(得分:0)
2019更新:工作流畅,轻松 https://material.io/develop/android/docs/getting-started/
如果您要使用材质组件,只需使用带有颜色或自定义可绘制对象的textCursorDrawable
。
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:textCursorDrawable="@color/red"
android:cursorVisible="true"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
答案 7 :(得分:0)
这是基于John's answer
的Xamarin解决方案 public static void SetCursorDrawableColor(EditText editText, Color color)
{
try
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
{
var gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.BottomTop, new[] { (int)color, color });
gradientDrawable.SetSize(SpToPx(2, editText.Context), (int)editText.TextSize);
editText.TextCursorDrawable = gradientDrawable;
return;
}
var fCursorDrawableRes =
Class.FromType(typeof(TextView)).GetDeclaredField("mCursorDrawableRes");
fCursorDrawableRes.Accessible = true;
int mCursorDrawableRes = fCursorDrawableRes.GetInt(editText);
var fEditor = Class.FromType(typeof(TextView)).GetDeclaredField("mEditor");
fEditor.Accessible = true;
Java.Lang.Object editor = fEditor.Get(editText);
Class clazz = editor.Class;
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
{
//TODO This solution no longer works in Android P because of reflection
// Get the drawable and set a color filter
Drawable drawable = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes);
drawable.SetColorFilter(color, PorterDuff.Mode.SrcIn);
var fCursorDrawable = clazz.GetDeclaredField("mDrawableForCursor");
fCursorDrawable.Accessible = true;
fCursorDrawable.Set(editor, drawable);
}
else
{
Drawable[] drawables = new Drawable[2];
drawables[0] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes).Mutate();
drawables[1] = ContextCompat.GetDrawable(editText.Context, mCursorDrawableRes).Mutate();
drawables[0].SetColorFilter(color, PorterDuff.Mode.SrcIn);
drawables[1].SetColorFilter(color, PorterDuff.Mode.SrcIn);
var fCursorDrawable = clazz.GetDeclaredField("mCursorDrawable");
fCursorDrawable.Accessible = true;
fCursorDrawable.Set(editor, drawables);
}
}
catch (ReflectiveOperationException) { }
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}
public static int SpToPx(float sp, Context context)
{
return (int)TypedValue.ApplyDimension(ComplexUnitType.Sp, sp, context.Resources.DisplayMetrics);
}
答案 8 :(得分:0)
您应该更改“ colorAccent”,并且为了不更改整个应用程序的此参数,可以使用ThemeOverlay。您可以在this article的最后一部分“光标和选择”中了解更多详细信息
答案 9 :(得分:0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (editText.getTextCursorDrawable() instanceof InsetDrawable) {
InsetDrawable insetDrawable = (InsetDrawable) editText.getTextCursorDrawable();
insetDrawable.setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_ATOP);
editText.setTextCursorDrawable(insetDrawable);
}
if (editText.getTextSelectHandle() instanceof BitmapDrawable) {
BitmapDrawable insetDrawable = (BitmapDrawable) editText.getTextSelectHandle();
insetDrawable.setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_ATOP);
editText.setTextSelectHandle(insetDrawable);
}
if (editText.getTextSelectHandleRight() instanceof BitmapDrawable) {
BitmapDrawable insetDrawable = (BitmapDrawable) editText.getTextSelectHandleRight();
insetDrawable.setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_ATOP);
editText.setTextSelectHandleRight(insetDrawable);
}
if (editText.getTextSelectHandleLeft() instanceof BitmapDrawable) {
BitmapDrawable insetDrawable = (BitmapDrawable) editText.getTextSelectHandleLeft();
insetDrawable.setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_ATOP);
editText.setTextSelectHandleLeft(insetDrawable);
}
}
在 Q (29) 之前参见:https://stackoverflow.com/a/44352565/2255331