app:srcCompat
avec ImageView
permet une utilisation rétrocompatible des dessins vectoriels. Mais comment pouvez-vous les utiliser avec d'autres View
s en plus de ImageView
? Par exemple, les attributs TextView
tels que Android:drawableLeft
.
L'utilisation du vecteur drawable en tant que Android:icon
avec MenuItem
a également provoqué un crash avec l'exception suivante:
Fatal Exception: Android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>
at Android.view.LayoutInflater.createView(LayoutInflater.Java:626)
at Android.view.LayoutInflater.createViewFromTag(LayoutInflater.Java:702)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:470)
at Android.view.LayoutInflater.inflate(LayoutInflater.Java:398)
at Android.support.v7.view.menu.MenuItemImpl.setActionView(MenuItemImpl.Java:621)
at Android.support.v7.view.menu.MenuItemImpl.setActionView(MenuItemImpl.Java:40)
at Android.support.v4.view.MenuItemCompat.setActionView(MenuItemCompat.Java:310)
at Android.support.v7.view.SupportMenuInflater$MenuState.setItem(SupportMenuInflater.Java:465)
at Android.support.v7.view.SupportMenuInflater$MenuState.addItem(SupportMenuInflater.Java:479)
at Android.support.v7.view.SupportMenuInflater.parseMenu(SupportMenuInflater.Java:196)
at Android.support.v7.view.SupportMenuInflater.inflate(SupportMenuInflater.Java:118)
at com.example.niceapp.context.main.MainActivity.onCreateOptionsMenu(MainActivity.Java:101)
at Android.app.Activity.onCreatePanelMenu(Activity.Java:2578)
Avec Support Library 23.2.0, comment résoudre ce problème?
Pour AppCompat version 23.3.0 où aucune solution de travail via le sélecteur XML (la réponse acceptée de razzledazzle), nous pouvons le faire par programme:
activity_main.xml
<Android.support.v7.widget.AppCompatImageButton
Android:id="@+id/btnEnter"
/>
MainActivity.Java
AppCompatImageButton image = (AppCompatImageButton) findViewById(R.id.btnEnter);
if (image != null) {
VectorDrawableCompat vcAccept = VectorDrawableCompat.create(getResources(), R.drawable.vc_accept, getTheme());
VectorDrawableCompat vcAcceptWhite = VectorDrawableCompat.create(getResources(), R.drawable.vc_accept_white, getTheme());
StateListDrawable stateList = new StateListDrawable();
stateList.addState(new int[]{Android.R.attr.state_focused, -Android.R.attr.state_pressed}, vcAccept);
stateList.addState(new int[]{Android.R.attr.state_focused, Android.R.attr.state_pressed}, vcAcceptWhite);
stateList.addState(new int[]{-Android.R.attr.state_focused, Android.R.attr.state_pressed}, vcAcceptWhite);
stateList.addState(new int[]{}, vcAccept);
image.setImageDrawable(stateList);
}
Ce code est équivalent pour ce sélecteur xml:
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_focused="true" Android:state_pressed="false" Android:drawable="@drawable/vc_accept" />
<item Android:state_focused="true" Android:state_pressed="true" Android:drawable="@drawable/vc_accept_white" />
<item Android:state_focused="false" Android:state_pressed="true" Android:drawable="@drawable/vc_accept_white" />
<item Android:drawable="@drawable/vc_accept" />
</selector>
Si le vecteur drawable n'est pas affiché à l'aide de l'API 23, vous devez d'abord convertir la variable VectorDrawable
en une variable Drawable
régulière. Si vous voulez utiliser setCompoundDrawablesWithIntrinsicBounds
, vous devrez le faire, mais pour StateListDrawable, je n'avais pas besoin de le faire.
Drawable icon;
if (Android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
icon = VectorDrawableCompat.create(getResources(), R.drawable.vc_icon, getContext().getTheme());
} else {
icon = getResources().getDrawable(R.drawable.vc_icon, getContext().getTheme());
}
Update 2: ils ont ajouté une option pour l'activer à nouveau dans Support Library 23.4.0:
Pour les utilisateurs d’AppCompat, nous avons ajouté une API d’inscription permettant de réactiver le support Vector Drawables à partir de ressources (comportement décrit dans 23.2) via AppCompatDelegate.setCompatVectorFromResourcesEnabled () - gardez à l’esprit que cela peut toujours causer problèmes d'utilisation de la mémoire et problèmes de mise à jour des instances de configuration, d'où leur désactivation par défaut.
Update: Cela ne fonctionne plus à partir de la version 23.3.0
Pour les utilisateurs d’AppCompat, nous avons décidé de supprimer la fonctionnalité qui vous permettent d'utiliser des vecteurs drawables à partir de ressources sur des périphériques antérieurs à Lollipop en raison de problèmes rencontrés dans la mise en œuvre de la version 23.2.0/23.2.1 [ https://code.google.com/p/Android/issues/detail?id=205236 } _, https://code.google.com/p/Android/issues/detail? id = 204708] . En utilisant app: srcCompat et setImageResource () continue de fonctionner.
De _ { développeur Android Google+ post } _
Utiliser AppCompat et app: srcCompat est la méthode la plus infaillible pour intégrer des vecteurs dessinables à des vecteurs dans votre application.
Cette citation provient de la version officielle de blogpost pour la publication de la version 23.2.0 de la bibliothèque de prise en charge.
Le poste mentionne également les éléments suivants:
Vous constaterez que les vecteurs pouvant être directement référencés en dehors de
app:srcCompat
échoueront avant Lollipop. Cependant,AppCompat
prend en charge le chargement des vecteurs dessinables de vecteurs lorsqu'ils sont référencés dans un autre conteneur dessinable tel queStateListDrawable
,InsetDrawable
,LayerDrawable
,LevelListDrawable
etRotateDrawable
. En utilisant cette indirection, vous pouvez utiliser des vecteurs dessrables vectoriels dans des cas tels que l’attributTextView
’sAndroid:drawableLeft
, qui ne serait normalement pas en mesure de prendre en charge les vecteurs drawables.
Cela se traduit par les étapes ci-dessous:
Étape 1:
Créez ou importez une ressource vectorielle dont vous avez besoin pour l'application. Par exemple, on peut créer un vecteur pouvant être dessiné pour l’icône de recherche et le nommer ic_action_search_vector.xml
Étape 2:
Créez une autre ressource pouvant être dessinée par proxy pour le vecteur dessiné précédemment créé. Supposons que, pour le ic_action_search_vector.xml
précédent, ic_action_search.xml
puisse être créé comme une simple StateListDrawable
pouvant contenir les lignes ci-dessous:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:drawable="@drawable/ic_action_search_vector"/>
</selector>
Cette étape peut être ignorée si vous avez référencé le vecteur pouvant être dessiné à partir d'une autre ressource que vous utiliserez et que vous utiliserez avec votre vue.
Étape 3:
Utilisez la ressource drawable (ici, ic_action_search.xml
) qui fait référence au vecteur drawable (ic_action_search_vector.xml
) au lieu du vecteur directement dessinable. Pour un menu, cela ressemblerait à:
<item Android:id="@+id/search"
Android:title="@string/search"
Android:icon="@drawable/ic_action_search"
app:showAsAction="always"/>
C'est la solution à ce problème!
Vector drawables peut être utilisé avant Lollipop ailleurs que app:srcCompat
, mais son prix est raisonnable.
J'ai créé ce diagramme pour aider (valable pour Support Library 23.4.0 à - au moins - 25.1.0).
Vous pouvez ajouter un vecteur pouvant être dessiné dans TextView par programme. Utilisez VectorDrawableCompat pour ajouter drawableLeft/drawableRight/drawableTop/drawableBottom/drawableStart/drawableEnd.
Pas:
je. Si TextView est à l'intérieur de l'activité:
TextView tvUserName= (TextView)findViewById(R.id.et_username_or_email);
VectorDrawableCompat drawableCompat=VectorDrawableCompat.create(getResources(), R.drawable.layer_list_ic_user, tvUserName.getContext().getTheme());
tvUserName.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableCompat, null, null, null);
ii. Si TextView est à l'intérieur de Fragment:
TextView tvUserName= (TextView )view.findViewById(R.id.et_username_or_email);
VectorDrawableCompat drawableCompat=VectorDrawableCompat.create(getActivity().getResources(), R.drawable.layer_list_ic_user, tvUserName.getContext().getTheme());
tvUserName.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableCompat, null, null, null);
Pour plus d'informations sur VectorDrawableCompat Référez-vous ceci lien _
Android 5.0 (API de niveau 21) et supérieur fournit un support pouvant être dessiné par vecteur. Si votre application a un niveau d'API minimum inférieur, Vector Asset Studio ajoute le fichier pouvant être dessiné par vecteur à votre projet. De plus, au moment de la construction, Gradle crée des images raster PNG à différentes résolutions. Gradle génère les densités PNG spécifiées par la propriété générée DSD (Domain Specific Language) dans un fichier build.gradle. Pour générer des fichiers PNG, le système de génération nécessite Android Plugin for Gradle 1.5.0 ou version ultérieure.
Ce n'est pas vrai si vous incluez dans votre note vectorDrawables.useSupportLibrary = true
soit mis à false, soit supprimez complètement la ligne et tous vos vecteurs fonctionneront comme ils étaient. Mais pour les anciennes versions d'Android, ils pourront compter sur le PNG converti.
définir le vecteur drawable à côté drawable dans TextView sous Android
AppCompatTextViewnow supporte app:drawableLeftCompat
, app:drawableTopCompat
, app:drawableRightCompat
, app:drawableBottomCompat
, app:drawableStartCompat
et app:drawableEndCompat
composés tirables, prenant en charge les types pouvant être attirés rétroportés tels que VectorDrawableCompat.
Inclure ceci dans votre dossier
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
Dans votre vue texte, vous pouvez utiliser
app:drawableLeftCompat
app:drawableStartCompat
Formulaire Android studio 3.0.0 Android: src n’est pas compatible avec les images vectorielles et inférieur à 21 pour l’exception d’obtention. utilisez app: srcCompat pour une image vectorielle. Conservez tous les fichiers d’image vectorielle dans le dossier drawable .
Android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Et dans la classe d'application, définissez ceci:
@Override
public void onCreate() {
super.onCreate();
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
Vous pouvez maintenant utiliser votre fichier .xml. N'oubliez pas d'utiliser ce lien: xmlns: app = "http://schemas.Android.com/apk/res-auto"
<RelativeLayout
Android:id="@+id/counterValuePanel"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="match_parent" >
<ImageView
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_cart_notify"/>
</RelativeLayout>
Maintenant, vous pouvez utiliser app: srcCompat = "@ drawable/ic_cart_notify" mais si vous essayez d'utiliser Android: background ou Android: drawableLeft, vous obtenez une exception "Erreur lors de l'inflation". Pour cela, créez un nouveau fichier .xml enroulable, ic_cart_notify est une icône vectorielle.
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:drawable="@drawable/ic_cart_notify"/>
</layer-list>
Dadou a raison. Donc, si vous souhaitez utiliser le sélecteur pour afficher avec VectorDrawables, vous devez ajouter:
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(trfor);
}
à chaque activité pour laquelle vous souhaitez utiliser VectorDrawables sur des appareils dotés de versions inférieures à Android 5.