5 votes

EditText Couleur de la poignée pour 28(P) avec 29(Q) comme API cible

Jusqu'à présent, j'ai utilisé la réflexion pour mettre à jour la poignée de sélection pour editTexts. Cela fonctionnait bien jusqu'à ce que je mette à jour l'api 29(Q).

Il semble que Google ait fait des mises à jour (ou Java, je ne suis pas tout à fait sûr), mais je reçois maintenant des messages comme :

Accès au champ caché Landroid/widget/Editor;->mDrawableForCursor:Landroid/graphics/drawable/Drawable ; (dark greylist, reflection)

Le point positif est que l'api 29 (après de nombreuses années) dispose d'une méthode stable pour définir la couleur de la poignée de manière programmatique. Malheureusement, elle n'est pas rétro-compatible pour autant que j'aie pu le découvrir et elle a également cassé des choses pour l'api 28. Tout ce qui est en dessous de l'api 28 fonctionne très bien avec la réflexion. Voici mon code qui fonctionne maintenant pour tout ce qui n'est pas l'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);
    }
}

Les arguments en faveur d'Android P sont détruits par la dernière mise à jour de Google :(

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

Ma question est la suivante : quelqu'un a-t-il réussi à définir par programme la couleur de la poignée en utilisant l'api 29 pour des appareils fonctionnant avec l'api 28 ?

Par souci de clarté, il s'agit de la poignée dont il est question : Android EditText Handle

0voto

htafoya Points 3207

Ne pouvez-vous pas le faire avec textField.setTextSelectHandle(drawable) ?

pour api < 29

// This avoids crash for api < 29: java.lang.NoSuchMethodError: No virtual method setTextSelectHandle
    private void setTextSelectHandle(@NonNull EditText editText, @NonNull Context context) {
        try {
            final Field fEditor = TextView.class.getDeclaredField("mEditor");
            fEditor.setAccessible(true);
            final Object editor = fEditor.get(editText);
            if (editor != null) {
                final Field fSelectHandleCenter = editor.getClass()
                        .getDeclaredField("mSelectHandleCenter");
                fSelectHandleCenter.setAccessible(true);
                fSelectHandleCenter.set(editor, context.getDrawable(R.drawable.disable_text_handle));
            }
        } catch (ReflectiveOperationException exception) {
            // no-op
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X