以编程方式设置文本光标图标

43
如果我在XML中添加了一个EditText,我可以设置textCursorDrawable="@null"
<EditText
    android:id="@+id/txtE3Casecode4"
    android:layout_width="30dp"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:background="#C7C7C5"
    android:textCursorDrawable="@null"
    android:ems="10"
    android:inputType="number"
    android:maxLength="2"
    android:text="01"
    android:textColor="#000000" />

现在我在Java中绘制一个EditText。我想要设置android:textCursorDrawable="@null"

LinearLayout.LayoutParams paramtext = new LinearLayout.LayoutParams(
    LinearLayout.LayoutParams.FILL_PARENT,
    LinearLayout.LayoutParams.WRAP_CONTENT);
EditText txtOther = new EditText(this);
txtOther.setLayoutParams(paramtext);
txtOther.setBackgroundColor(Color.WHITE);
txtOther.setTextColor(Color.BLACK);
txtOther.setId(99999);
// txtOther.setCursorDrawable ?                                

如何设置它?

7个回答

70

2019年更新: 没有公共API可用于设置光标的Drawable。有关29及以上API的可用API,请参见https://dev59.com/dWgu5IYBdhLWcg3wHzsX#57555148,在此之前,您需要按照下面的描述使用反射。

在API 29之前,您可以使用反射在程序中设置光标。字段mCursorDrawableRes没有改变,因此这应该适用于所有设备,除非制造商更改了某些内容或稍后更改了它。

使用反射设置光标:

EditText yourEditText = new EditText(context);

...

try {
    // 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);
} catch (Exception ignored) {
}

在您的应用程序中定义一个光标可绘制项:

<?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>

另一种方法:

您还可以使用以下方法设置光标颜色:

public static void setCursorDrawableColor(EditText editText, int color) {
    try { 
        Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
        fCursorDrawableRes.setAccessible(true);
        int mCursorDrawableRes = fCursorDrawableRes.getInt(editText);
        Field fEditor = TextView.class.getDeclaredField("mEditor");
        fEditor.setAccessible(true);
        Object editor = fEditor.get(editText);
        Class<?> clazz = editor.getClass();
        Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable");
        fCursorDrawable.setAccessible(true);
        Drawable[] drawables = new Drawable[2];
        drawables[0] = editText.getContext().getResources().getDrawable(mCursorDrawableRes);
        drawables[1] = editText.getContext().getResources().getDrawable(mCursorDrawableRes);
        drawables[0].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        drawables[1].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        fCursorDrawable.set(editor, drawables);
    } catch (Throwable ignored) {
    } 
} 

完美运行,标记为正确答案。 - Corbella
将此标记为答案。反射类的使用效果非常好。我已经测试过它的工作。 - V_J
1
涉及反射的任何内容都不应该被推荐,即使它能解决问题。 - Alex Fu
1
@AlexFu,Android支持库使用反射。我同意如果可能的话应该避免使用,但不应该被忽视。 - Jared Rummler
2
这将在Android 10上崩溃。任何未记录的方法访问都受到限制。https://developer.android.com/distribute/best-practices/develop/restrictions-non-sdk-interfaces - Sanmoy
显示剩余3条评论

9

没有这样的方法。 - user9599745
1
从API级别29开始添加,将您的SDK编译为29。https://developer.android.com/reference/android/widget/TextView#setTextCursorDrawable(android.graphics.drawable.Drawable) - Muhammed Yalçın Kuru
你可以尝试这个 https://dev59.com/dWgu5IYBdhLWcg3wHzsX#65068255 - iamkdblue

2
这对我有用。
 public void setCursorDrawable(@DrawableRes int resId) {
        if (mEditText == null)
            return;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            mEditText.setTextCursorDrawable(resId);
            return;
        }
        try {
            @SuppressLint("SoonBlockedPrivateApi") Field field = TextView.class.getDeclaredField("mCursorDrawableRes");
            field.setAccessible(true);
            field.set(mEditText, resId);
        } catch (Throwable throwable) {
            Logger.e(TAG, throwable);
        }
    }
}

1

答案是---------------------->无法实现。

事实上,在我的工作中我也遇到过这个问题,但在查看google文档和源代码后,我发现你无法在Java代码中设置此属性。

TextView类中,您可以找到以下代码:

case com.android.internal.R.styleable.TextView_textCursorDrawable:
    mCursorDrawableRes = a.getResourceId(attr, 0);
    break;

但是方法textCursorDrawable()只存在于R.attr中,如果你想设置这个属性,你只能在XML文件中包含一个editText,并调用下面的构造方法。

public EditText(Context context, AttributeSet attrs) {
    this(context, attrs, com.android.internal.R.attr.editTextStyle);
}

我正在寻找类似且相关的内容,这是原文链接:https://dev59.com/53zaa4cB1Zd3GeqPPF5z - Rickster

0
如果您使用AppCompat库并且您的Activity扩展了AppCompatActivity,则可以使用XML样式colorAccent设置文本光标的颜色(适用于所有EditText)。
<style name="AppTheme" parent="@style/Theme.AppCompat">
    <item name="colorAccent">#FF4081</item>
</style>

这适用于 Android 5+,并向后兼容旧版 Android 版本,从 Android 4.4 (API 19) 到 Android 4.0 (API 14)。注意:如果您正在使用 AutoCompleteTextView,请确保其任何自定义子类都扩展了 AppCompatAutoCompleteTextView,否则文本光标样式将无法工作。

另请参阅此指南,了解如何将颜色强调(色调)应用于对话框按钮:Android v21 Theme.Appcompat color accent is ignored, no padding on dialogs


0

MySharedPreferences().color = 十六进制颜色 -> #FF5733

以编程方式实现的方法

    fun EditText.standardSimpleEditText(){
    this.apply {
        highlightColor = getColorWithAlpha(getValidateColorHex(MySharedPreferences().color), 0.2f)

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
            val drawable = ContextCompat.getDrawable(this.context, R.drawable.cursor) as Drawable
            val customDrawable = tintDrawable(drawable, MySharedPreferences().color)
            textCursorDrawable = customDrawable
        }
    }
}

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="@color/colorBlack" />
    <size android:width="1.8dp" />
</shape>

验证颜色十六进制

fun getValidateColorHex(color: Int = MySharedPreferences().color): Int{
    val hexColor = "#"+Integer.toHexString(color).substring(2)
    val validateColor = Color.parseColor(hexColor)
    return validateColor
}

-1

你应该使用TextInputLayout,因为现在已经是2020年了,它可以在所有设备上正常工作。

<com.google.android.material.textfield.TextInputLayout
    style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="30dp"
        android:layout_marginTop="26dp"
        android:layout_marginEnd="30dp"
        android:theme="@style/TextInputLayoutAppearance"
        app:endIconMode="clear_text"
        app:hintEnabled="false">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/gallery_search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fontFamily="@font/inter_medium"
            android:hint="Hint here"
            android:inputType="text"
            android:cursorVisible="true"
            android:focusable="true"
            />

    </com.google.android.material.textfield.TextInputLayout>

这是主要的,请不要忘记添加它,您可以从这里更改光标的颜色。

<style name="TextInputLayoutAppearance" parent="Widget.Design.TextInputLayout">
        <item name="colorControlNormal">@color/black</item>
        <item name="colorControlActivated">@color/black</item>
        <item name="colorControlHighlight">@color/blue</item>
    </style>

有关TextInputLayout的更多信息,请访问此处:https://material.io/develop/android/components/text-fields


问题是关于如何以编程方式实现... 您的答案仅在 XML 中描述它。 - Leandro Borges Ferreira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接