Utilisation de drawables vecteur Android sur crash pré Lollipop

J'utilise vector drawables dans android avant Lollipop et ce sont quelques-unes de mes bibliothèques et versions d'outils:

  • Android Studio: 2.0
  • Plugin Android Gradle: 2.0.0
  • Outils De Construction: 23.0.2
  • Bibliothèque De Support Android: 23.3.0

J'ai ajouté cette propriété dans mon niveau d'application Build.Gradle

android {  
  defaultConfig {  
    vectorDrawables.useSupportLibrary = true  
   }  
}

Il convient également de mentionner que j'utilise un drawable supplémentaire tel que LayerDrawable (layer_list) comme indiqué dans Android Blog officiel (lien ici ) pour définir les drawables pour les drawables vectoriels en dehors de app:srcCompat

<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/search"/>
</level-list>

Vous trouverez directement des références vectorielles à l'extérieur de application: srcCompat échouera avant Lollipop. Cependant, AppCompat fait supporte le chargement des drawables vectoriels lorsqu'ils sont référencés dans un autre conteneur drawable tel Qu'un StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable et RotateDrawable. En utilisant ce indirection, vous pouvez utilisez des drawables vectoriels dans des cas tels que TextView Android: attribut drawableLeft, qui ne serait normalement pas capable de vecteurs de support un drawable.

Quand j'utilise app:srcCompat Tout fonctionne bien, mais quand j'utilise:

android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom

Sur ImageView, ImageButton, TextView ou EditText avant la Sucette, elle lève une exception:

Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
48
demandé sur Juliet Wanjohi 2016-04-26 17:04:31

12 réponses

Je pense que cela se produit parce que le vecteur de Support a été désactivé dans la dernière version de la bibliothèque: 23.3.0

Selon ce POST - :

Pour les utilisateurs D'AppCompat, nous avons décidé de supprimer la fonctionnalité qui vous permet d'utiliser des drawables vectoriels à partir de ressources sur les périphériques pré-Lollipop en raison de problèmes trouvés dans l'implémentation dans la version 23.2.0/23.2.1 (numéro 205236). Utilisation de l'application: srcCompat et setImageResource () continue de fonctionner.

Si vous visitez problème problème 205236 , il semble qu'ils permettront à l'avenir mais le problème de mémoire ne sera pas résolu bientôt:

Dans la prochaine version, j'ai ajouté une API opt-in où vous pouvez réactiver le support VectorDrawable qui a été supprimé. Il est livré avec les mêmes mises en garde qu'auparavant (utilisation de la mémoire et problèmes de mise à jour de la Configuration).

J'ai eu un problème similaire. Donc, dans mon cas, j'ai rétabli toutes les icônes qui utilisent à nouveau le vecteur drawable de la ressource aux images PNG (puisque le problème de mémoire continuera à se produire même après qu'ils fournissent une option pour l'activer à nouveau).

Je ne suis pas sûr si c'est la meilleure option, mais cela corrige tous les accidents à mon avis.

Mise à JOUR

Ils ont réactivé ce VectorDrawable dans
bibliothèque de Support Android 23.4.0

Pour les utilisateurs D'AppCompat , nous avons ajouté une API opt-in pour réactiver les Drawables vectoriels de support à partir des ressources (le comportement trouvé dans 23.2) via AppCompatDelegate.setCompatVectorFromResourcesEnabled (true) - gardez à l'esprit que cela peut toujours causer des problèmes d'utilisation de la mémoire et des problèmes de mise à jour des instances de Configuration, d'où la désactivation par défaut.

Peut être, build.gradle le paramètre est maintenant obsolète et vous avez juste besoin de l'activer dans les activités appropriées (cependant, besoin de tester).

Maintenant, pour l'activer, vous devez faire:

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

    ...
}
61
répondu W0rmH0le 2018-06-26 13:22:32

Pour élaborer sur l'autre de très bonnes réponses , Voici un diagramme qui peut vous aider. Il est valide si vous avez une bibliothèque de Support de 23.4.0 à au moins 25.1.0.

Cheatsheet VectorDrawable

42
répondu David Ferrand 2017-05-23 12:34:17

J'ai eu le même problème. Mais faire beaucoup de R & D j'ai eu la réponse.

Pour Imageview et ImageButton utiliser, app: srcCompat= " @drawable/...." et pour d'autres vues comme Button, Textview, au lieu d'utiliser "drawableLeft/right..."dans le XML, spécifiez les drawables par programmation comme suit:

button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);

Et utilisez "AppCompatResources" pour obtenir le drawable.

37
répondu Shashank Kapsime 2017-10-10 05:27:00

La réponse de Guillherme P est assez géniale. Juste pour faire une petite amélioration, vous n'avez pas besoin d'ajouter cette ligne dans chaque activité, si vous l'avez ajoutée une fois dans la classe Application, cela fonctionnera également.

public class App extends Application {

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

Rappelez-vous: vous devez toujours avoir activé l'utilisation de la bibliothèque de support dans gradle:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Assurez-vous également que vous utilisez une version de bibliothèque de support supérieure à v23.4, Lorsque Google a ajouté la prise en charge des conteneurs Drawable pour VectorDrawables (note de version )

NOTE : quoi qu'il en soit, je suggère d'utiliser les fichiers PNG jusqu'à ce que Google trouve une meilleure solution ou que vous ayez des problèmes de mémoire.

25
répondu Benny 2016-11-22 01:27:32

VectorDrawables sur pré-lollipop devrait fonctionner correctement sans utiliser

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

Si vous voulez utiliser VectorDrawables dans ImageViews, vous pouvez utiliser L'attribut srcCompat et cela fonctionnera, mais à L'intérieur des boutons ou des TextViews IL ne sera pas , vous devez donc envelopper le Drawable dans un InsetDrawable ou un LayerDrawable. Il y a une autre astuce que j'ai découverte, si vous utilisez la liaison de données, vous pouvez le faire:

android:drawableLeft="@{@drawable/vector_ic_access_time_24px}"
android:drawableStart="@{@drawable/vector_ic_access_time_24px}"

Cela fonctionnera comme par magie, je n'ai pas enquêté sur ce qui se passe derrière les scènes, mais je suppose que le TextView utilise la méthode getDrawable de L'AppCompatResources ou similaire.

8
répondu cesards 2016-11-23 10:04:50

J'ai eu le même problème. Et corrigez-le en supprimant

vectorDrawables.useSupportLibrary = true

MA version cible est 25 et la bibliothèque de support est

 compile 'com.android.support:appcompat-v7:25.3.1'
7
répondu Rajesh Nasit 2017-09-12 11:21:40

Pour tous ceux qui mettent à niveau vers Android gradle 3.0 et supérieur, il n'est pas nécessaire d'utiliser AppCompatDelegate.setCompatVectorFromResourcesEnabled(true), ou de définir vectorDrawables.useSupportLibrary = true (Ajouter cela causera un problème) et d'utiliser app:srcCompat, cela fonctionne.

Prenez-moi deux jours pour comprendre cela, et n'ont pas trouvé de documents connexes dans les documents de google...

4
répondu Geng Jiawen 2018-07-12 01:30:25

J'utilise VectorDrawables sur les appareils pré-lollipop et voici comment je le fais: -

Étape 1: Mettez ceci dans votre gradle de niveau d'application.

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Étape 2:

Mettez ceci dans votre classe D'Application et n'oubliez pas d'enregistrer votre classe D'Application dans le fichier manifeste.

public class App extends Application {
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }
}

Étape 3:

Obtenir VectorDrawables en utilisant,

imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
2
répondu Parag Kadam 2017-09-30 06:34:08

Beaucoup de R & d, enfin obtenir cette solution pour les accidents sur les appareils pré-lollipop.

Pour Imageview

  • utiliser app:srcCompat, au lieu d'android:src

Pour TextView / EditText

  • Supprime drawableleft,drawableright.... et défini à partir du code java drawable.

Txtview.setCompoundDrawablesWithIntrinsicbounds (AppCompatResources.getDrawable (EventDetailSinglePage.ce, R. drawable.ic_done_black_24_n), null, null, null);

Pour Construire.gradle

VectorDrawables.useSupportLibrary = true

2
répondu Jatin Mandanka 2018-08-15 07:09:17

La suggestion de Guilherme P ne fonctionnait pas pour moi. Je suis allé de l'avant et j'ai pris la décision d'utiliser png où je dois faire des choses en dehors de l'application:srcCompat c'est-à-dire drawableLeft, drawableRight, etc. C'était un changement assez facile à faire, et n'a pas les problèmes de mémoire potentiels AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); introduit.

-2
répondu Ryan Newsom 2017-03-27 17:06:27

Il existe une solution plus simple maintenant, il suffit d'utiliser app: drawableRightCompat à partir de l'espace de noms de l'application.

Ou dans le style:

<style name="YourStyle">
    <item name="drawableRightCompat">@drawable/your_vector</item>
</style>
-2
répondu southerton 2018-01-26 11:12:38

Une alternative à la réponsede de Benny est de créer une superclasse Activity:

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

  //...
}

Maintenant étendre VectorDrawableActivity au lieu de AppCompatActivity.

-3
répondu Code-Apprentice 2016-11-10 02:05:40