Gestion des vecteurs Drawables sur Android 4.4 et versions antérieures

Lors du développement d'applications Android, l'utilisaiton de ressources vectorielles (SVG convertis en XML) peut provoquer des plantages sur les appareils équipés d'une version d'Android inférieure à 5.0 (API 21). L'erreur classique rencontrée est la suivante : org.xmlpull.v1.XmlPullParserException: Binary XML file line #1: invalid drawable tag vector.

1. Configuration du projet et de l'environnement

La première étape consiste à configurer correctement Gradle pour permettre le support rétroactif des vecteurs via la bibliothèque de suport.

Dans le fichier build.gradle de votre module, ajoutez les dépendances nécessaires :

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:support-vector-drawable:28.0.0'
}

Ensuite, activez explicitement le support des vecteurs dans la section defaultConfig :

android {
    defaultConfig {
        // Pour Gradle 2.0 et supérieur
        vectorDrawables.useSupportLibrary = true
    }
}

Si vous utilisez une version très ancienne de Gradle (entre 1.5 et 2.0), la configuration diffère légèrement :

android {
    defaultConfig {
        generatedDensities = []
    }
    aaptOptions {
        additionalParameters "--no-version-vectors"
    }
}

2. Activation du support au niveau de l'Activity

Pour s'assurer que les ressources vectorielles sont correctement chargées via les ressources système, il est indispensable d'activer un commutateur spécifique dans votre classe Activity (qui doit hériter de AppCompatActivity). La méthode la plus robuste consiste à utiliser un bloc statique :

public class BaseActivity extends AppCompatActivity {
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ...
    }
}

3. Utilisation correcte dans les fichiers de mise en page (Layouts)

L'attribut standard android:src ne fonctionne pas de manière fiable avec les vecteurs sur les anciennes versions d'Android. Vous devez utiliser l'attribut défini dans l'espace de noms de l'application :

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/ic_mon_vecteur" />

Notez que si votre Activity n'hérite pas directement de AppCompatActivity, vous devrez utiliser explicitement le composant AppCompatImageView dans votre fichier XML.

4. Conteneurs pour les composants secondaires (Buttons, TextViews)

Sur Android 5.0 et versions antérieures, l'utilisation directe d'un vecteur dans un Button ou comme compoundDrawable dans un TextView peut échouer. La solution consiste à encapsuler le vecteur dans un conteneur comme un selector ou une layer-list.

Exemple d'un fichier res/drawable/ic_wrapper.xml :

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/mon_vecteur_original" />
</selector>

Vous pouvez ensuite appliquer ce wrapper à n'importe quel composant :

<Button
    android:id="@+id/btn_action"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Valider"
    android:drawableLeft="@drawable/ic_wrapper" />

5. Cas particulier des TextViews

Le composant AppCompatTextView ne supporte pas nativement l'inflation des vecteurs via les attributs android:drawableStart ou android:drawableTop sur les anciennes API. Si l'astuce du selector ne suffit pas, il est recommandé de définir les icônes programmatiquement ou d'utiliser une implémentation personnalisée de TextView qui surcharge la gestion des drawables pour intercepter et charger correctement les ressources vectorielles.

Étiquettes: Android VectorDrawable AppCompat Android-Gradle XML

Publié le 26 juillet à 21h33