EditText处理28(P)的颜色,以29(Q)作为目标API

时间:2019-08-05 14:09:55

标签: android android-edittext customization programmatically

到目前为止,我一直在使用反射,因此请更新editTexts的选择句柄。在我更新为目标API 29(Q)之前,它一直工作良好。

似乎Google进行了一些更新(或完全不确定Java),但是我现在收到类似以下消息:

  

访问隐藏字段Landroid / widget / Editor;-> mDrawableForCursor:Landroid / graphics / drawable / Drawable; (暗灰色列表,反射)

从好的方面来说,API 29(经过很多年)具有通过编程方式设置手柄颜色的稳定方法。不幸的是,它不能像我所发现的那样向后兼容,并且它也破坏了api 28的功能。api 28之下的所有内容都可以在反射下正常工作。在我的代码下方,该代码现在可用于除API 28以外的任何功能

 /**
 * Sets the color for the cursor and handles on the {@link EditText editText}.
 *
 * @throws EditTextTintError if an error occurs while tinting the view.
 */
public void apply() throws EditTextTintError {
    try {
        // Get the editor
        Field field = TextView.class.getDeclaredField("mEditor");
        field.setAccessible(true);
        Object editor = field.get(editText);

        if (cursorColor != null) {
            editText.setHighlightColor(ColorUtils.setAlphaComponent(cursorColor, 40));

            // Get the cursor drawable, tint it, and set it on the TextView Editor
            // Get the cursor resource id
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                ColorFilter colorFilter = new BlendModeColorFilter(cursorColor, BlendMode.SRC_ATOP);
                editText.getTextCursorDrawable().mutate().setColorFilter(colorFilter);
                editText.getTextSelectHandle().mutate().setColorFilter(colorFilter);
                editText.getTextSelectHandleLeft().mutate().setColorFilter(colorFilter);
                editText.getTextSelectHandleRight().mutate().setColorFilter(colorFilter);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                try {
                    Field fieldP = TextView.class.getDeclaredField("mCursorDrawableRes");
                    fieldP.setAccessible(true);
                    int drawableResId = fieldP.getInt(editText);

                    // Get the editor
                    fieldP = TextView.class.getDeclaredField("mEditor");
                    fieldP.setAccessible(true);
                    Object editorP = fieldP.get(editText);

                    // Get the drawable and set a color filter
                    Drawable drawable = ContextCompat.getDrawable(editText.getContext(), drawableResId);
                    drawable.setColorFilter(cursorColor, PorterDuff.Mode.SRC_ATOP);

                    // Set the drawables
                    fieldP = editorP.getClass().getDeclaredField("mDrawableForCursor");
                    fieldP.setAccessible(true);
                    fieldP.set(editorP, drawable);
                } catch (final Exception ignored) {
                    ignored.printStackTrace();
                }
            } else {
                String[] resFieldNames = {"mTextSelectHandleLeftRes", "mTextSelectHandleRightRes", "mTextSelectHandleRes"};
                String[] drawableFieldNames = {"mSelectHandleLeft", "mSelectHandleRight", "mSelectHandleCenter"};
                Integer[] colors = {selectHandleLeftColor, selectHandleRightColor, selectHandleMiddleColor};
                for (int i = 0; i < resFieldNames.length; i++) {
                    Integer color = colors[i];
                    if (color == null) {
                        continue;
                    }

                    String resFieldName = resFieldNames[i];
                    String drawableFieldName = drawableFieldNames[i];

                    field = TextView.class.getDeclaredField(resFieldName);
                    field.setAccessible(true);
                    int selectHandleRes = field.getInt(editText);

                    Drawable selectHandleDrawable = ContextCompat.getDrawable(editText.getContext(), selectHandleRes).mutate();
                    selectHandleDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);

                    field = editor.getClass().getDeclaredField(drawableFieldName);
                    field.setAccessible(true);
                    field.set(editor, selectHandleDrawable);
                }
            }
        }
    } catch (Exception e) {
        throw new EditTextTintError("Error applying tint to " + editText, e);
    }
}

基本上,Android P的情况已被Google的最新更新所破坏:(

else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    // insert working code here :D
} 

我的问题,是否有人能够使用目标api 29以编程方式设置在api 28上运行的设备的手柄颜色?

为清楚起见,这是指的句柄: Android EditText Handle

1 个答案:

答案 0 :(得分:0)

您不能用textField.setTextSelectHandle(drawable)这样做吗?