71 votes

Sélecteur Android à dessiner avec VectorDrawables srcCompat

Je suis confronté à un problème avec le nouveau compatibilité descendante avec VectorDrawables. Dans la Bibliothèque de prise en charge 23.2 a été une nouvelle fonctionnalité pour assurer la compatibilité avec Android VectorDrawables indroduced.

J'ai une ImageView qui est un SelectorDrawable attribué. Cette Drawable est titulaire de plusieurs VectorDrawables alors j'ai pensé que je devrais utiliser app:srcCompat pour la compatibilité. Mais il ne fonctionne pas sur mon Galaxy S2 avec android 4.1.2.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_gps_fixed_24dp"android:state_activated="true" android:state_selected="true"></item>
    <item android:drawable="@drawable/ic_gps_not_fixed_24dp" android:state_activated="true" android:state_selected="false"></item>
    <item android:drawable="@drawable/ic_gps_not_fixed_24dp" android:state_activated="false" android:state_selected="true"></item>
    <item android:drawable="@drawable/ic_gps_off_24dp" android:state_activated="false" android:state_selected="false"></item>
    <item android:drawable="@drawable/ic_gps_not_fixed_24dp"></item>
</selector>

Tous un drawable sont vecteur de fichiers xml.

Lors de l'utilisation de ce SelectorDrawable avec srcCompat, j'obtiens cette erreur:

  Caused by: android.content.res.Resources$NotFoundException: File res/drawable/  Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ic_gps_fixed_24dp.xml from drawable resource ID #0x7f0201c1
                                                                           at android.content.res.Resources.loadDrawable(Resources.java:1951)
                                                                           at android.content.res.Resources.getDrawable(Resources.java:672)
                                                                           at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173)
                                                                           at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:881).xml from drawable resource ID #0x7f0201c1

en utilisant android:src est encore pire.

Si j'utilise le vecteur d'un drawable avec l'app:srcCompat tous fonctionne bien. Donc je suppose que c'est un problème avec le SelectorDrawable et de la compatibilité.

Quelqu'un a eu le même problème et trouvé une solution ou est-il actuellement pas possible d'utiliser VectorDrawables dans SelectorDrawables avant Android 5?

Les Faits En Bref:

  • Cible de compilation API 23
  • Soutien Libraray 23.3.0
  • vectorDrawables.useSupportLibrary = true
  • Gradle 2.0

70voto

marilion91 Points 1107

certaines choses ont changé depuis que j'ai posé cette question alors je vais répondre moi-même.

Avec le Soutien de la Bibliothèque 23.4.0 le soutien pour VectorDrawables de Ressources a été réactivé: Android Support Library 23.4.0 maintenant disponible

Vous pouvez trouver plus d'informations sur ce dans cette fonte de la Google I/O de 2016: Ce qui est nouveau dans la bibliothèque de prise en charge - Google I/O de 2016

Vous avez besoin d'ajouter ce pour toutes les Activités où vous souhaitez utiliser VectorDrawables sur les appareils sous Android 5.0 (nom de Code Sucette, API de niveau 21):

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

Ainsi, vous pouvez maintenant utiliser VectorDrawables dans DrawableContainers mais il peut encore causer des problèmes comme mentionné dans les sources ci-dessus afin de l'utiliser avec prudence.

Je n'ai pas de réactiver cette fonctionnalité dans mon application, mais je vais changer beaucoup de mes icônes de VectorDrawables avec ma prochaine mise à jour majeure et va alors plonger plus profondément dans ce sujet.

64voto

Delargo Points 300

@Jahnold mentionnées dans le commentaire à la question, support pour le chargement de vecteur dessiné à partir d'un état du xml xml de la liste a été supprimée dans 23.3.

Cependant, j'ai trouvé plusieurs approches qui peuvent aider.

1. À L'Aide De La Teinte

L'approche est bien adaptée si l'un drawable partir de l'état sélectionné de la liste de différence seulement par des couleurs.

Tout d'abord, créez un seul vecteur dessinés avec teinte et blanc fillColor:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tintMode="multiply"
    android:tint="@color/button_tint">

    <path
        android:fillColor="#ffffff"
        android:pathData="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>

    <path
        android:pathData="M0 0h24v24H0z"/>

</vector>

Deuxièmement, créer de la couleur de l'etat liste button_tint.xml placés en res/color

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#555555" android:state_enabled="false"/>
    <item android:color="#6699dd"/>
</selector>

N'oubliez pas d'ajouter de suivre les lignes d' build.gradle ou l'approche ne fonctionnera pas sur les anciennes versions d'Android.

defaultConfig {
    vectorDrawables.useSupportLibrary = true
}

2. Coder en dur la création d' StateListDrawable

L'approche est adaptée si vous utilisez de l'état de la liste de vecteur d'un drawable qui différence non seulement une couleur, mais aussi par une figure si vous avez besoin de créer plusieurs fichiers xml. Ensuite, vous pouvez créer StateListDrawable par programme, comme indiqué dans une réponse.

7voto

vovaxo Points 177

Après avoir regardé Ce qui est nouveau dans la bibliothèque de prise en charge - Google I/O de 2016 , j'ai remarqué une méthode utile pour l' AppCompatResources classe. C'est - AppCompatResources#getColorStateList(Context context, int resId). Avec une aide de cette méthode, je ai mis en place le sélecteur de vecteur avec un drawable. Voici ma sélection de couleur dans le fichier icon_selector:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/red_selected" android:state_selected="true"/>
    <item android:color="@color/red_pressed" android:state_pressed="true"/>
    <item android:color="@color/red"/>
</selector>

Et il est en java une méthode qui retourne teinté drawable:

private Drawable getTintedDrawable(@DrawableRes int drawableId) {
    Drawable drawable;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        drawable = getResources().getDrawable(drawableId, getTheme());
    } else {
        drawable = getResources().getDrawable(drawableId);
    }
    drawable = DrawableCompat.wrap(drawable);
    DrawableCompat.setTintList(drawable.mutate(), AppCompatResources.getColorStateList(this, R.color.selector_nav_bar_item_ico));
    return drawable;
}

Vous pouvez l'utiliser comme indiqué ci-dessous

yourImageView.setImageDrawable(getTintedDrawable(R.drawable.ic_vector_image));

4voto

Raja Peela Points 638

Fonctionne bien avec les changements ci-dessous.

 static {
 AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
 

Ajouté dans la classe d'application.
app build.gradle dans defaultConfig

 vectorDrawables.useSupportLibrary = true
 

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