web-dev-qa-db-fra.com

Utilisation du vecteur Android Drawables sur le crash de Lollipop avant

J'utilise des dessins vectoriels dans Android avant Lollipop et ceux-ci font partie de certaines de mes bibliothèques et versions d'outil:

  • Android Studio: 2.0 
  • Android Gradle Plugin: 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 est également intéressant de mentionner que j’utilise un dessin supplémentaire, tel que LayerDrawable (layer_list), comme indiqué dans le blog officiel Android ( lien ici ), pour le réglage des dessinables pour les vecteurs dessinables 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 un vecteur de référence se rapportant à l'extérieur de app: srcCompat échouera avant Lollipop. Cependant, AppCompat fait supporte le dessin des vecteurs dessinables quand ils sont référencés dans un autre conteneur dessinable tel que StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable et RotateDrawable. En utilisant ceci indirection, vous pouvez utiliser des dessins vectoriels dans des cas tels que TextView Android: attribut drawableLeft, qui ne serait normalement pas en mesure de support vectoriel tirables.

Lorsque j'utilise app:srcCompat, tout fonctionne bien, mais lorsque j'utilise:

Android:background
Android:drawableLeft
Android:drawableRight
Android:drawableTop
Android:drawableBottom

sur ImageView, ImageButton, TextView ou EditText avant Lollipop, il déclenche une expection: 

Caused by: Android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
62
Behzad Bahmanyar

Je pense que cela se produit car Support Vector a été désactivé dans la dernière version de la bibliothèque: 23.3.0.

Selon ceci POST :

Pour les utilisateurs d’AppCompat, nous avons décidé de supprimer la fonctionnalité qui vous permet d’utiliser des éléments dessinables vectoriels à partir de ressources sur des appareils antérieurs à Lollipop en raison de problèmes rencontrés lors de l’implémentation de la version 23.2.0/23.2.1 (NUMÉRO 205236) . L'utilisation de app: srcCompat et setImageResource () continue de fonctionner.

Si vous visitez le numéro NUMÉRO 205236 , il semble que cela sera possible à l'avenir, mais le problème de mémoire ne sera pas résolu rapidement:

Dans la prochaine version, j'ai ajouté une API opt-in permettant de réactiver le support VectorDrawable supprimé. Il présente toutefois les mêmes réserves qu’avant (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 à nouveau toutes les icônes qui utilisent un vecteur tirable depuis une ressource vers des images PNG (car le problème de mémoire continuera de se produire même après qu’elles offrent une option pour le réactiver).

Je ne suis pas sûr que ce soit la meilleure option, mais à mon avis, cela corrige tous les crashs.

METTRE &AGRAVE; 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 afin de réactiver le support Vector Drawables à partir de ressources (comportement décrit dans 23.2) via AppCompatDelegate.setCompatVectorFromResourcesEnabled (true) - n'oubliez pas que cela Cela peut toujours entraîner des problèmes d’utilisation de la mémoire et des problèmes de mise à jour des instances de configuration, d’où sa désactivation par défaut.

Le paramètre Maybe, build.gradle est maintenant obsolète et vous devez simplement l'activer dans les activités appropriées (cependant, vous devez effectuer un test).

Maintenant, pour l'activer, vous devez faire:

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

    ...
}
64
W0rmH0le

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

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

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

Et utilisez "AppCompatResources" pour obtenir le dessinable.

49
Shashank Kapsime

Pour élaborer l'autre très bonne réponse , voici un diagramme qui peut vous aider. Il est valide si vous avez Support Library de 23.4.0 à au moins 25.1.0.

VectorDrawable cheatsheet

47
David Ferrand

La réponse de Guillherme P est assez impressionnante. 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);
}

N'OUBLIEZ PAS: 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 la bibliothèque de support supérieure à v23.4 lorsque Google a rajouté le support des conteneurs pouvant être dessinés pour VectorDrawables ( release note ).

Mettre à jour

Et pour les changements de code:

  1. Assurez-vous de mettre à jour app:srcCompat à chaque endroit qui accepte l'attribut Android:src (le IDE vous avertira s'il est invalide, comme pour la balise <bitmap>).
  2. Pour les attributs drawableLeft, drawableStart, drawableRight, drawableEnd utilisés dans TextView et des vues similaires, vous devrez les définir par programme pour l'instant. Un exemple de paramètre drawableStart:

    Drawable drawable = AppCompatResources.getDrawable(
            getContext(),
            R.drawable.your_vector_drawable);
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null);
    }
    
33
Benny

J'ai eu le même problème. Et le réparer en enlevant 

vectorDrawables.useSupportLibrary = true

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

 compile 'com.Android.support:appcompat-v7:25.3.1'
11
Rajesh Nasit

VectorDrawables sur pré-Lollipop devrait bien fonctionner sans utiliser

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

Si vous souhaitez utiliser VectorDrawables dans ImageViews, vous pouvez utiliser l'attribut srcCompat et cela fonctionnera, mais à l'intérieur de Buttons ou de TextViews, il ne sera pas ; vous devez donc insérer le dessin dans un InsetDrawable ou un LayerDrawable. Il y a un autre truc que j'ai découvert, si vous utilisez la liaison de données, vous pouvez faire ceci:

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

Comme par magie, je n’ai pas enquêté sur ce qui se passe dans les coulisses, mais je suppose que TextView utilise la méthode getDrawable de AppCompatResources ou similaire.

8
cesards

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

  • Supprimez drawableleft , drawableright .... et définissez-le à partir de code Java modifiable.

txtview.setCompoundDrawablesWithIntrinsicBounds (AppCompatResources.getDrawable (EventDetailSinglePage.this, R.drawable.ic_done_black_24_n), null, null, null);

Pour Build.gradle

vectorDrawables.useSupportLibrary = true

5
Jatin Mandanka

Pour ceux qui passent à Android Gradle version 3.0 ou ultérieure, il n’est pas nécessaire d’utiliser AppCompatDelegate.setCompatVectorFromResourcesEnabled(true), ni de définir vectorDrawables.useSupportLibrary = true (ajouter que cela pose problème) et d’utiliser app:srcCompat, cela fonctionne.

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

4
Geng Jiawen

J'utilise VectorDrawables sur des périphériques Pre-Lollipop et voici comment je le fais: -

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

Android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Étape 2:

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

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

Étape 3:

Obtenez VectorDrawables en utilisant,

imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
2
Parag Kadam

Après avoir utilisé le code ci-dessous.

Android {
  defaultConfig {
  vectorDrawables.useSupportLibrary = true  
                }
        }




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

encore, le problème des images vectorielles existe pour les attributs ci-dessous sont

DrawableEnd, DrawableStart, DrawableTop, DrawableBottom, Arrière-plan

Dans ce cas, veuillez suivre les instructions ci-dessous. Au lieu de référencer une image vectorielle, utilisez directement la balise selector en tant que fichier dessinable intermédiaire.

Exemple:

ic_warranty_icon.xml

<vector xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:width="17dp"
Android:height="24dp"
Android:autoMirrored="true"
Android:viewportWidth="17"
Android:viewportHeight="24">

<path
    Android:fillColor="#fff"
    Android:pathData="M10.927,15.589l-1.549,0.355a7.47,7.47 0,0 1,-0.878 0.056c-4.136,0 -7.5,-3.364 -7.5,-7.5s3.364,-7.5 7.5,-7.5 7.5,3.364 7.5,7.5c0,3.286 -2.126,6.078 -5.073,7.089zM8.5,2a6.508,6.508 0,0 0,-6.5 6.5c0,3.583 2.917,6.5 6.5,6.5s6.5,-2.917 6.5,-6.5 -2.917,-6.5 -6.5,-6.5z" />

safe_ic_warranty_icon.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:drawable="@drawable/ic_warranty_icon"  />
</selector>

Votre TextView/Layout.

<TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:drawableStart="@drawable/ic_warranty_icon"
       />


<LinearLayout
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:background="@drawable/ic_warranty_icon"
       />
0
Rajesh Gr

Il suffit de superposer un vecteur pouvant être dessiné dans une liste d'états, puis le problème sera résolu

Par exemple, vous avez une image vectorielle de flèche de retour:

ic_back_arrow.xml

oui, vous devez le superposer à la liste des couches xml (ic_back_arrow_vector_vector.xml):

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:drawable="@drawable/ic_back_arrow"/>
</layer-list>

Parce que la logique:

vectorDrawables.useSupportLibrary = true

et

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

ne vous aidera pas sur certains appareils en Chine et sur des appareils Samsung plus anciens. Si vous ne les superposez pas, cela échouera.

0
mr.boyfox

Nous avons essayé 3 choses

vectorDrawables.useSupportLibrary = true

Définition de setCompatVectorFromResourcesEnabled dans la classe d'application

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

Et utilisez app:srcCompat

Mais même après ça échouait avec

Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008

ensuite, nous avons compris que notre SVG avait une balise Gradient. La conversion de la balise de dégradé en chemins individuels pour l'API ci-dessous <= 23 et l'utilisation de la même API SVG> = 24 ont fonctionné.

A obtenu de l'aide de cette réponse https://stackoverflow.com/a/47783962/217151

0
Aalap

Moyen le plus simple d'utilisation:

  app:drawableRightCompat ="@drawable/ic_mobilelogin"
  app:drawableEndCompat="@drawable/ic_mobilelogin"
app:srcCompat="@drawable/ic_mobile"

et ... utilisez simplement l'application: ** Compat pour la compatibilité

Ajoutez également le support sur buil.gradle (Module)

Android {
 defaultConfig {
vectorDrawables.useSupportLibrary = true
               }
        }
0
Hamed Jaliliani