34 votes

Dessin vectoriel dans la liste des calques sur les anciennes versions d'Android

Sur les nouvelles versions d'Android, le code suivant:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
            <shape android:shape="oval">
                <solid android:color="#bdbdbd" />
                <size
                    android:width="60dp"
                    android:height="60dp" />
            </shape>
    </item>
    <item
        android:drawable="@drawable/ic_library_books_black_24dp"
        android:gravity="center"
        android:width="40dp"
        android:height="40dp"
        >
    </item>
</layer-list>

produit parfaitement ce:

Vector drawable showing white lists on grey circular background

Cependant, les précédentes versions d'Android (API 16 et 19, de ce que j'ai testé) n'aime pas cela du tout et j'ai

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: package.app, PID: 11490
              android.view.InflateException: Binary XML file line #26: Error inflating class ImageView

sur l'inflation. Je l'ai utilisé, app:srcCompat pour tous mes ImageViews donc il n'y a pas de problème.

La norme du Vecteur un drawable aussi bien fonctionner, mais lorsqu'il est placé dans un layer-list - ils provoquer le chaos. Existe-il des solutions?

34voto

La largeur/hauteur des attributs pour le vecteur dessinés dans votre couche-liste sont uniquement pris en charge dans l'API 23 (Guimauve) et plus élevé. Si vous regardez votre couche-liste drawable dans l'Android Studio de l'éditeur, ces attributs doivent avoir blocs jaunes autour d'eux avec un avertissement que cela ne fonctionne pas de manière fiable sur des appareils plus anciens.

Mais je pense que vous pouvez vous débarrasser de l'avertissement et obtenir le même effet de centrage comme ceci:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="oval">
            <solid android:color="#bdbdbd" />
            <size
                android:width="60dp"
                android:height="60dp" />
        </shape>
    </item>
    <item
        android:drawable="@drawable/ic_library_books_black_24dp"
        android:top="10dp"
        android:bottom="10dp"
        android:left="10dp"
        android:right="10dp">
    </item>
</layer-list>

J'ai testé cela sur une ancienne API 15 téléphone et il a bien fonctionné. J'espère que cela fonctionne pour vous aussi.

Mise à jour:

Dans une version précédente de cette réponse, j'avais déconseillé d'utiliser vectorDrawables.useSupportLibrary = true avec couche de listes, car il provoquait des plantages. Cependant, j'ai récemment entendu parler d'une solution qui semble corriger le crash (tout en évitant la graisse auto-généré les fichiers png que @développeur android correctement mentionné). Voici un résumé de ce qui doit être fait pour qu'il fonctionne correctement:

Assurez-vous d'utiliser srcCompat dans votre xml.

    <android.support.v7.widget.AppCompatImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:srcCompat="@drawable/layer_list_with_svg" />

Ajouter " vectorDrawables.useSupportLibrary' app/build.gradle

 android {
   defaultConfig {
     vectorDrawables.useSupportLibrary = true
   }
 }

Ajouter " setCompatVectorFromResourcesEnabled(true)' à onCreate

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    setContentView(R.layout.activity_main);
}

Pourquoi est-tout-ce nécessaire?

En tant que plus informé personne me l'a expliqué, cela a à voir avec la façon dont Android charges jusqu'à la compat vecteur un drawable. Si vous utilisez vectorDrawables.useSupportLibrary = true alors vues d'images vous permettra de charger jusqu' VectorDrawableCompat un drawable lorsque vous utilisez app:srcCompat. Lorsque votre liste de couche drawable est gonflé, il n'y a aucun moyen pour elle de comprendre comment créer ces référencé vecteur un drawable. Mais si vous allumez setCompatVectorFromResourcesEnabled il va essayer d'accrocher le vecteur dessiné de chargement à un niveau beaucoup plus bas que l'image de point de vue et leur app:srcCompat d'attribut, de sorte qu'il est alors en mesure de comprendre comment charger le vecteur d'un drawable référencé dans la liste des calques.

9voto

Lewis McGeary Points 4926

Cette réponse s'appuie sur l'article AppCompat - l'Âge des Vecteurs par Chris Banes(qui travaille sur la Bibliothèque de prise en charge). Pour cette question, nous sommes à la recherche spécifiquement à la section intitulée La "magie" façon.

L'incident que vous rencontrez est parce que le Soutien de la Bibliothèque permet seulement quelques façons d'utiliser VectorDrawables par défaut, et couche-la liste n'est pas l'un d'eux.

Il existe un bloc de code que vous pouvez ajouter à la partie supérieure de votre Activité afin de permettre aux autres VectorDrawable comme <layer-list>:

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

Remarque: l'article lié contient une faute de frappe dans cette nom de la méthode, à l'aide de "FromSources", il devrait être "FromResources" comme indiqué ci-dessus.

Vous auriez besoin d'ajouter cela à chaque Activité où vous voulez l'utiliser tel un drawable, ou peut-être l'inclure dans un BaseActivity classe que vos autres Activités s'étendent à partir.

Pour l'article, cela devrait signifier que la suite va maintenant travailler:

DrawableContainers qui font référence à d'autres un drawable ressources qui contiennent seulement un vecteur de ressources.

...StateListDrawable...InsetDrawable, LayerDrawable, LevelListDrawable et RotateDrawable.

Il convient de noter cependant, cette méthode est fortement enraciné avec le mot "peut", cela peut fonctionner, et il n'est pas activé par défaut, donc, être conscient et de vérifier qu'il est vraiment pour vous!

Maintenant, il y a effectivement une autre dimension à cette question, de crédit à d'autres utilisateurs Selim Ajimi et Raiponce Van Winkle , pour résoudre ce dans leurs réponses. <layer-list> a certaines différences de comportement entre les API, en particulier l' width et height attributs de votre <item> seulement être pris en charge dans l'API 23+. Ce n'est pas la cause de la panne, ni la cause de votre app crash veut dire que votre image ne sera pas regarder comme prévu une fois que vous avez en fonctionnement de plus tôt dans l'Api.

La suggestion de Raiponce Van Winkle semble en effet être un bon moyen pour positionner le drawable correctement à travers des Api (testé sur les API 16 et 24):

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="oval">
            <solid android:color="#bdbdbd" />
            <size
                android:width="60dp"
                android:height="60dp" />
        </shape>
    </item>
    <item
        android:drawable="@drawable/ic_library_books_black_24dp"
        android:top="10dp"
        android:bottom="10dp"
        android:left="10dp"
        android:right="10dp"
        >
    </item>
</layer-list>

1voto

Selim Ajimi Points 266
 <?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
</layer-list>
 

Comme vous pouvez le voir ici n'a pas d'attributs largeur / hauteur ...

Vous pouvez ajouter Bitmap à l'élément Je pense que c'est la meilleure solution

1voto

android developer Points 20939

Le soutien pour VectorDrawble sur les anciennes versions d'Android est assez limité, en supposant que vous utilisez vectorDrawables.useSupportLibrary = true :

Vous pouvez utiliser VectorDrawableCompat retour à l'API de niveau 7 et AnimatedVectorDrawableCompat sur tous les appareils fonctionnant sous Android 5.0 (API niveau 11) et plus élevé. La façon dont Android charges un drawable, et pas à chaque endroit qui accepte un drawable ID, comme dans un fichier XML, prend en charge le chargement vecteur d'un drawable. Le android.de soutien.v7.appcompat paquet a ajouté une nombre de fonctionnalités pour le rendre facile à utiliser de vecteur d'un drawable. Tout d'abord, lorsque vous utilisez android.de soutien.v7.appcompat paquet avec ImageView ou avec des sous-classes telles que ImageButton et FloatingActionButton, vous pouvez l'utilisation de la nouvelle application:srcCompat attribut de référence vecteur comme un drawable bien que tous les autres drawable disponible pour android:src

Même dans le code, vous êtes limité:

Pour changer un drawable au moment de l'exécution, vous pouvez utiliser le setImageResource() méthode que précédemment. À l'aide de AppCompat et application:srcCompat est le plus l'infaillible méthode de l'intégration de vecteur d'un drawable dans votre application.

Que pouvez-vous faire?

Quelques solutions possibles:

  1. d'autres dessinés pour la VectorDrawable que vous utilisez dans la LayerDrawable. Mettre dans res/drawable-xxhdpi, par exemple, et la VectorDrawable dans res/drawable-anydpi .

  2. ne pas utiliser vectorDrawables.useSupportLibrary = true jusqu'à ce que vous avez l'application ont une minSdk qui est capable d'utiliser VectorDrawable. Cela fonctionne parce que l'IDE va générer les fichiers PNG pour vous.

  3. créer le layerList par programmation (exemple ici), et afin de mettre la VectorDrawable, utilisez AppCompatResources.getDrawable . Vous pourriez également être en mesure de le faire avec XML, à l'exception de la partie de la mise de la VectorDrawable.

BTW, la raison qu'elle est limitée, c'est que Google a échoué à rendre efficace et sans problèmes. Vous pouvez obtenir d'origine de la tentative d'avoir un support complet, en utilisant AppCompatDelegate.setCompatVectorFromResourcesEnabled(vrai) , mais que les docs disent, vous prenez un risque ici:

Cette fonction est par défaut désactivé, depuis l'activation peut provoquer des problèmes avec l'utilisation de la mémoire et des problèmes de mise à jour de la Configuration des instances. Si vous mettez à jour la configuration manuellement, vous ne voulez probablement pas pour permettre cela. Vous avez été averti.

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