Android 以编程方式更改颜色编辑文本选择句柄

Android 以编程方式更改颜色编辑文本选择句柄,android,Android,我正在尝试以编程方式更改edittext的颜色。它可以工作,但正如您从所附的图像中看到的,文本选择的图标仍然使用主题颜色重音,而不是我设置的蓝色。我怎样才能改变它?我目前的代码是: editText.setBackgroundTintList(new ColorStateList(new int[][]{StateSet.WILD_CARD}, new int[]{color})); setCursorDrawableColor(editText, color); private void s

我正在尝试以编程方式更改edittext的颜色。它可以工作,但正如您从所附的图像中看到的,文本选择的图标仍然使用主题颜色重音,而不是我设置的蓝色。我怎样才能改变它?我目前的代码是:

editText.setBackgroundTintList(new ColorStateList(new int[][]{StateSet.WILD_CARD}, new int[]{color}));
setCursorDrawableColor(editText, color);

private 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];
        Resources res = editText.getContext().getResources();
        drawables[0] = res.getDrawable(mCursorDrawableRes);
        drawables[1] = res.getDrawable(mCursorDrawableRes);
        drawables[0].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        drawables[1].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        fCursorDrawable.set(editor, drawables);
    } catch (final Throwable ignored) {
    }
}
editText.setBackgroundTintList(新的ColorStateList(新的int[]{StateSet.WILD_CARD},新的int[]{color}));
setCursorDrawableColor(编辑文本,颜色);
私有void setCursorDrawableColor(EditText EditText,int-color){
试一试{
字段fCursorDrawableRes=TextView.class.getDeclaredField(“mCursorDrawableRes”);
fcursordrawalables.setAccessible(true);
int-mCursorDrawableRes=fCursorDrawableRes.getInt(编辑文本);
字段fEditor=TextView.class.getDeclaredField(“mEditor”);
fEditor.setAccessible(true);
对象编辑器=fEditor.get(editText);
Class clazz=editor.getClass();
字段fCursorDrawable=clazz.getDeclaredField(“mCursorDrawable”);
fCursorDrawable.setAccessible(true);
可提取[]可提取=新可提取[2];
Resources res=editText.getContext().getResources();
drawables[0]=res.getDrawable(mCursorDrawableRes);
可提取文件[1]=可提取文件(mCursorDrawableRes);
drawables[0].setColorFilter(color,PorterDuff.Mode.SRC_-IN);
drawables[1].setColorFilter(color,PorterDuff.Mode.SRC_-IN);
fCursorDrawable.set(编辑器,可绘制文件);
}捕获(忽略最终丢弃){
}
}

我更喜欢使用
styles.xml
来设置样式。但是,可以按如下方式以编程方式进行:

1。突出显示颜色

首先是突出显示颜色。这可以通过使用以下选项进行设置:

editText.setHighlightColor(color);
2。左右标记

左侧和右侧标记仍然没有用此标记着色。继续使用反射方法,我们应该对这些选择标记执行相同的操作:

// Left
Field fCursorDrawableLeftRes = TextView.class.getDeclaredField("mTextSelectHandleLeftRes");
fCursorDrawableLeftRes.setAccessible(true);
int mCursorDrawableLeftRes = fCursorDrawableLeftRes.getInt(editText);

// Right
Field fCursorDrawableRightRes = TextView.class.getDeclaredField("mTextSelectHandleRightRes");
fCursorDrawableRightRes.setAccessible(true);
int mCursorDrawableRightRes = fCursorDrawableRightRes.getInt(editText);
当然还有:将其添加到drawables列表以更新它们(从您的来源更新):

3。结果

这意味着您的方法将类似于:

private void setCursorDrawableColor(EditText editText, int color) {
    try {
        Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
        fCursorDrawableRes.setAccessible(true);
        int mCursorDrawableRes = fCursorDrawableRes.getInt(editText);

        // Left
        Field fCursorDrawableLeftRes = TextView.class.getDeclaredField("mTextSelectHandleLeftRes");
        fCursorDrawableLeftRes.setAccessible(true);
        int mCursorDrawableLeftRes = fCursorDrawableLeftRes.getInt(editText);

        // Right
        Field fCursorDrawableRightRes = TextView.class.getDeclaredField("mTextSelectHandleRightRes");
        fCursorDrawableRightRes.setAccessible(true);
        int mCursorDrawableRightRes = fCursorDrawableRightRes.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[3];
        Resources res = editText.getContext().getResources();
        drawables[0] = res.getDrawable(mCursorDrawableRes);
        drawables[1] = res.getDrawable(mCursorDrawableLeftRes);
        drawables[2] = res.getDrawable(mCursorDrawableRightRes);
        drawables[0].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        drawables[1].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        drawables[2].setColorFilter(color, PorterDuff.Mode.SRC_IN);
        fCursorDrawable.set(editor, drawables);
    } catch (final Throwable ignored) {}
}

(当然还有突出显示的
textColorHighlight

Kotlin版本,适用于api 14到api 29

fun setHandlesColor(textView: TextView, @ColorInt color: Int) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val size = 22.spToPx(textView.context).toInt()
        val corner = size.toFloat() / 2
        val inset = 10.spToPx(textView.context).toInt()

        //left drawable
        val drLeft = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(color, color))
        drLeft.setSize(size, size)
        drLeft.cornerRadii = floatArrayOf(corner, corner, 0f, 0f, corner, corner, corner, corner)
        textView.setTextSelectHandleLeft(InsetDrawable(drLeft, inset, 0, inset, inset))

        //right drawable
        val drRight = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(color, color))
        drRight.setSize(size, size)
        drRight.cornerRadii = floatArrayOf(0f, 0f, corner, corner, corner, corner, corner, corner)
        textView.setTextSelectHandleRight(InsetDrawable(drRight, inset, 0, inset, inset))

        //middle drawable
        val drMiddle = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(color, color))
        drMiddle.setSize(size, size)
        drMiddle.cornerRadii = floatArrayOf(0f, 0f, corner, corner, corner, corner, corner, corner)
        val mInset = (sqrt(2f) * corner - corner).toInt()
        val insetDrawable = InsetDrawable(drMiddle, mInset, mInset, mInset, mInset)
        val rotateDrawable = RotateDrawable()
        rotateDrawable.drawable = insetDrawable
        rotateDrawable.toDegrees = 45f
        rotateDrawable.level = 10000
        textView.setTextSelectHandle(rotateDrawable)
        return
    }

    try {
        val editorField = try {
            TextView::class.java.getDeclaredField("mEditor")
                .apply { if (!isAccessible) isAccessible = true }
        } catch (t: Throwable) {
            null
        }
        val editor = if (editorField == null) textView else editorField[textView]
        val editorClass: Class<*> =
            if (editorField == null) TextView::class.java else editor.javaClass

        val handleNames = arrayOf(
            "mSelectHandleLeft",
            "mSelectHandleRight",
            "mSelectHandleCenter"
        )
        val resNames = arrayOf(
            "mTextSelectHandleLeftRes",
            "mTextSelectHandleRightRes",
            "mTextSelectHandleRes"
        )
        for (i in handleNames.indices) {
            val handleField = editorClass.getDeclaredField(handleNames[i])
                .apply { isAccessible = true }

            val handleDrawable = handleField.get(editor) as? Drawable?
                ?: TextView::class.java.getDeclaredField(resNames[i])
                    .apply { isAccessible = true }
                    .run { getInt(textView) }
                    .let { ContextCompat.getDrawable(textView.context, it) }

            if (handleDrawable != null) {
                val tinted = tintDrawable(handleDrawable, color)
                handleField.set(editor, tinted)
            }
        }
    } catch (e: java.lang.Exception) {
        e.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)
}
fun setHandlesColor(textView:textView,@ColorInt color:Int){
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.Q){
val size=22.spToPx(textView.context).toInt()
val corner=size.toFloat()/2
val inset=10.spToPx(textView.context).toInt()
//左牵引
val drLeft=GradientDrawable(GradientDrawable.Orientation.BOTTOM_-TOP,intArrayOf(颜色,颜色))
drLeft.setSize(大小,大小)
drLeft.cornerRadii=floatArrayOf(角、角、0f、0f、角、角、角)
textView.setTextSelectHandleLeft(可插入绘制(drLeft,inset,0,inset,inset))
//右拉深
val drRight=GradientDrawable(GradientDrawable.Orientation.BOTTOM_-TOP,intArrayOf(颜色,颜色))
drRight.setSize(大小,大小)
drRight.cornerRadii=floatArrayOf(0f,0f,角,角,角,角,角,角)
textView.settextSelectHandlerRight(可插入绘制(drRight,inset,0,inset,inset))
//中拉深
val drMiddle=GradientDrawable(GradientDrawable.Orientation.BOTTOM_-TOP,intArrayOf(颜色,颜色))
drMiddle.setSize(大小,大小)
drMiddle.cornerRadii=floatArrayOf(0f,0f,角,角,角,角,角,角)
val mInset=(sqrt(2f)*拐角-拐角).toInt()
val insetDrawable=insetDrawable(drMiddle,mInset,mInset,mInset,mInset)
val rotatedravable=rotatedravable()
RotatedRavable.drawable=可插入绘制
旋转可移动角度=45f
rotatedravable.level=10000
textView.setTextSelectHandle(可旋转)
返回
}
试一试{
val editorField=try{
TextView::class.java.getDeclaredField(“mEditor”)
.apply{if(!isAccessible)isAccessible=true}
}捕获(t:可丢弃){
无效的
}
val editor=if(editorField==null)textView else editorField[textView]
val editorClass:类=
if(editorField==null)TextView::class.java else editor.javaClass
val handleNames=阵列(
“mSelectHandleLeft”,
“MSelectHandlerRight”,
“mSelectHandleCenter”
)
val resNames=arrayOf(
“mTextSelectHandleLeftRes”,
“MTextSelectHandlerRights”,
“MTextSelectHandlers”
)
对于(i在handleNames.索引中){
val handleField=editorClass.getDeclaredField(handleNames[i])
.apply{isAccessible=true}
val handleDrawable=handleField.get(编辑器)为?可绘制?
?:TextView::class.java.getDeclaredField(resNames[i])
.apply{isAccessible=true}
.run{getInt(textView)}
.let{ContextCompat.getDrawable(textView.context,it)}
if(可处理的!=null){
val着色=着色可绘制(可处理绘制,彩色)
handleField.set(编辑器,着色)
}
}
}catch(e:java.lang.Exception){
e、 printStackTrace()
}
}
有趣的数字.spToPx(上下文:上下文?=null):浮点{
val res=context?.resources?:android.content.res.resources.getSystem()
返回TypedValue.applyDimension(TypedValue.COMPLEX\u UNIT\u SP,this.toFloat(),res.displayMetrics)
}
趣味着色可绘制(可绘制:可绘制,@ColorInt颜色:Int):可绘制{
(可绘制为?矢量可绘制兼容)
?应用{setTintList(ColorStateList.valueOf(color))}
?.让{返回它}
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.LOLLIPOP){
(可绘制为矢量绘制)
?申请{setTintList(Co
<item name="colorControlNormal">@android:color/holo_green_dark</item>
<item name="colorControlActivated">@android:color/holo_green_dark</item>
<item name="colorControlHighlight">@android:color/holo_green_dark</item>
fun setHandlesColor(textView: TextView, @ColorInt color: Int) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val size = 22.spToPx(textView.context).toInt()
        val corner = size.toFloat() / 2
        val inset = 10.spToPx(textView.context).toInt()

        //left drawable
        val drLeft = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(color, color))
        drLeft.setSize(size, size)
        drLeft.cornerRadii = floatArrayOf(corner, corner, 0f, 0f, corner, corner, corner, corner)
        textView.setTextSelectHandleLeft(InsetDrawable(drLeft, inset, 0, inset, inset))

        //right drawable
        val drRight = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(color, color))
        drRight.setSize(size, size)
        drRight.cornerRadii = floatArrayOf(0f, 0f, corner, corner, corner, corner, corner, corner)
        textView.setTextSelectHandleRight(InsetDrawable(drRight, inset, 0, inset, inset))

        //middle drawable
        val drMiddle = GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, intArrayOf(color, color))
        drMiddle.setSize(size, size)
        drMiddle.cornerRadii = floatArrayOf(0f, 0f, corner, corner, corner, corner, corner, corner)
        val mInset = (sqrt(2f) * corner - corner).toInt()
        val insetDrawable = InsetDrawable(drMiddle, mInset, mInset, mInset, mInset)
        val rotateDrawable = RotateDrawable()
        rotateDrawable.drawable = insetDrawable
        rotateDrawable.toDegrees = 45f
        rotateDrawable.level = 10000
        textView.setTextSelectHandle(rotateDrawable)
        return
    }

    try {
        val editorField = try {
            TextView::class.java.getDeclaredField("mEditor")
                .apply { if (!isAccessible) isAccessible = true }
        } catch (t: Throwable) {
            null
        }
        val editor = if (editorField == null) textView else editorField[textView]
        val editorClass: Class<*> =
            if (editorField == null) TextView::class.java else editor.javaClass

        val handleNames = arrayOf(
            "mSelectHandleLeft",
            "mSelectHandleRight",
            "mSelectHandleCenter"
        )
        val resNames = arrayOf(
            "mTextSelectHandleLeftRes",
            "mTextSelectHandleRightRes",
            "mTextSelectHandleRes"
        )
        for (i in handleNames.indices) {
            val handleField = editorClass.getDeclaredField(handleNames[i])
                .apply { isAccessible = true }

            val handleDrawable = handleField.get(editor) as? Drawable?
                ?: TextView::class.java.getDeclaredField(resNames[i])
                    .apply { isAccessible = true }
                    .run { getInt(textView) }
                    .let { ContextCompat.getDrawable(textView.context, it) }

            if (handleDrawable != null) {
                val tinted = tintDrawable(handleDrawable, color)
                handleField.set(editor, tinted)
            }
        }
    } catch (e: java.lang.Exception) {
        e.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)
}
    public static void SetHandlesColor(EditText editText, Color color)
        {

            try
            {
                if (Build.VERSION.SdkInt >= BuildVersionCodes.Q)
                {
                    var size = SpToPx(22, editText.Context);
                    var corner = size / 2f;
                    var inset = SpToPx(10, editText.Context);

                    //left drawable
                    var drLeft = new GradientDrawable(GradientDrawable.Orientation.BottomTop, new[] { (int)color, color });
                    drLeft.SetSize(size, size);
                    drLeft.SetCornerRadii(new[] { corner, corner, 0f, 0f, corner, corner, corner, corner });
                    editText.TextSelectHandleLeft = new InsetDrawable(drLeft, inset, 0, inset, inset);

                    //right drawable
                    var drRight = new GradientDrawable(GradientDrawable.Orientation.BottomTop, new[] { (int)color, color });
                    drRight.SetSize(size, size);
                    drRight.SetCornerRadii(new[] { 0f, 0f, corner, corner, corner, corner, corner, corner });
                    editText.TextSelectHandleRight = new InsetDrawable(drRight, inset, 0, inset, inset);

                    //middle drawable
                    var drMiddle = new GradientDrawable(GradientDrawable.Orientation.BottomTop, new[] { (int)color, color });
                    drMiddle.SetSize(size, size);
                    drMiddle.SetCornerRadii(new[] { 0f, 0f, corner, corner, corner, corner, corner, corner });
                    var mInset = (int)(System.Math.Sqrt(2f) * corner - corner);
                    var insetDrawable = new InsetDrawable(drMiddle, mInset, mInset, mInset, mInset);
                    var rotateDrawable = new RotateDrawable();
                    rotateDrawable.Drawable = insetDrawable;
                    rotateDrawable.ToDegrees = 45f;
                    rotateDrawable.SetLevel(10000);
                    editText.TextSelectHandle = rotateDrawable;
                    return;
                }

                var editorField = Class.FromType(typeof(TextView)).GetDeclaredField("mEditor");
                if (!editorField.Accessible)
                    editorField.Accessible = true;

                var editor = editorField.Get(editText);
                var editorClass = editor.Class;
                string[] handleNames = { "mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter" };
                string[] resNames = { "mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes" };

                for (int i = 0; i < handleNames.Length; i++)
                {
                    var handleField = editorClass.GetDeclaredField(handleNames[i]);
                    if (!handleField.Accessible)
                    {
                        handleField.Accessible = true;
                    }
                    Drawable handleDrawable = (Drawable)handleField.Get(editor);

                    if (handleDrawable == null)
                    {
                        var resField = Class.FromType(typeof(TextView)).GetDeclaredField(resNames[i]);
                        if (!resField.Accessible)
                        {
                            resField.Accessible = true;

                        }
                        int resId = resField.GetInt(editText);
                        handleDrawable = ContextCompat.GetDrawable(editText.Context, resId);

                    }

                    if (handleDrawable != null)
                    {
                        Drawable drawable = handleDrawable.Mutate();
                        drawable.SetColorFilter(color, PorterDuff.Mode.SrcIn);
                        handleField.Set(editor, drawable);
                    }
                }
            }
            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);
        }