Java 如何在android中以编程方式更改Edittext光标颜色?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25996032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Change programmatically Edittext Cursor Color in android?
提问by Amit Prajapati
In android we can change the cursor color via:
在android中,我们可以通过以下方式更改光标颜色:
android:textCursorDrawable="@drawable/black_color_cursor"
.
android:textCursorDrawable="@drawable/black_color_cursor"
.
How can we do this dynamically?
我们如何动态地做到这一点?
In my case I have set cursor drawable to white, but i need to change black How to do ?
就我而言,我已将光标可绘制设置为白色,但我需要更改为黑色怎么办?
// Set an EditText view to get user input
final EditText input = new EditText(nyactivity);
input.setTextColor(getResources().getColor(R.color.black));
采纳答案by Jared Rummler
Using some reflection did the trick for me
使用一些反射对我有用
Java:
爪哇:
// 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:
<?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>
Here is a method that you can use that doesn't need an XML:
这是您可以使用的不需要 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) {
}
}
回答by Orest Savchak
android:textCursorDrawable="@null"
Then in the application:
然后在应用程序中:
final EditText input = new EditText(nyactivity);
input.setTextColor(getResources().getColor(R.color.black));
回答by Oleg Barinov
This is a rewritten version of the function from @Jared Rummlerwith a couple of improvements:
这是@Jared Rummler函数的重写版本,有一些改进:
- Support for Android 4.0.x
- The special
getDrawable(Context, int)
function sience thegetDrawable(int)
is deprecated for API 22 and above.
- 支持安卓 4.0.x
- API 22 及更高版本不推荐使用特殊
getDrawable(Context, int)
函数 siencegetDrawable(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);
}
}
回答by Rotem
We managed to do it by:
我们设法做到了:
- Creating a layout file with just an EditText and the cursor color set in xml on it.
- Inflating it
- Using the EditText as you would use a programmatically created one
- 创建一个布局文件,只包含一个 EditText 和在 xml 中设置的光标颜色。
- 给它充气
- 像使用以编程方式创建的那样使用 EditText
回答by Hrishikesh Kadam
Inspired from @Jared Rummlerand @Oleg BarinovI have crafted solution which works on API 15 also -
受@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);
}
}
回答by Amit Prajapati
2019 Updated:working smooth and easy https://material.io/develop/android/docs/getting-started/
2019 更新:工作顺畅且轻松 https://material.io/develop/android/docs/getting-started/
If you are using material component just simply use textCursorDrawable
with color or your custom drawable.
如果您正在使用材料组件,只需简单地使用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>
回答by John
Kotlin version, works from api 14 to api 29
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)
}
回答by stepkillah
Here is the solution for Xamarin based on John'sanswer
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);
}
回答by Dmitriy Lesovoy
You should change "colorAccent" and in order not to change this parameter for the whole application you can use ThemeOverlay. You can read more detailed in this article, the last section "Cursor and Selection"
您应该更改“colorAccent”,为了不更改整个应用程序的此参数,您可以使用 ThemeOverlay。您可以在这篇文章中阅读更详细的内容,最后一节“光标和选择”