Est-il possible d’utiliser VectorDrawable dans Buttons and TextViews en utilisant Android: DrawableRight?

Lorsque j’utilise les ressources VectorDrawable dans une vue text ou imageview, j’obtiens un plantage à l’exécution lorsque j’utilise “android: DrawableRight” / “android: DrawableEnd” / “android: DrawableStart” / “android: DrawableLeft”.

L’application comstackra bien sans aucun avertissement.

j’utilise

  • Gradle 1.5
  • Bibliothèque de support 23.2 (‘com.android.support:appcompat-v7:23.2.0’)

Ce que j’ai trouvé, cependant, c’est que je peux assigner par programmation des fichiers SVG en Java sans planter comme ça.

TextView tv = (TextView) findViewById(R.id.textView); tv.setCompoundDrawablesWithInsortingnsicBounds(null,null, getResources().getDrawable(R.drawable.ic_accessible_white_36px),null); 

(Je soupçonne que ceci est un bogue de la bibliothèque de support pour 23.2.)

Mais est-il possible d’utiliser drawableRight, etc. pour les ressources SVG?

Voici ma mise en page

     

Voici mon activité

 package au.com.angryitguy.testsvg; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } } 

Voici l’actif VectorDrawable non modifié du site de conception de matériel de Google.

     

Voici mon app build.gradle

 apply plugin: 'com.android.application' android { comstackSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "au.com.angryitguy.testsvg" minSdkVersion 16 targetSdkVersion 23 versionCode 1 versionName "1.0" // Stops the Gradle plugin's automatic rasterization of vectors generatedDensities = [] } // Flag to tell aapt to keep the atsortingbute ids around aaptOptions { additionalParameters "--no-version-vectors" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { comstack fileTree(dir: 'libs', include: ['*.jar']) testComstack 'junit:junit:4.12' comstack 'com.android.support:appcompat-v7:23.2.0' } 

Voici le crash. (Notez les erreurs de gonflement qui font référence à la textview.)

 03-02 07:56:08.808 13863-13863/? E/AndroidRuntime: FATAL EXCEPTION: main java.lang.RuntimeException: Unable to start activity ComponentInfo{au.com.angryitguy.testsvg/au.com.angryitguy.testsvg.MainActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class TextView at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) at android.app.ActivityThread.access$600(ActivityThread.java:130) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method) Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class TextView at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) at android.view.LayoutInflater.inflate(LayoutInflater.java:489) at android.view.LayoutInflater.inflate(LayoutInflater.java:396) at android.view.LayoutInflater.inflate(LayoutInflater.java:352) at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14) at android.app.Activity.performCreate(Activity.java:5008) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) at android.app.ActivityThread.access$600(ActivityThread.java:130) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method) Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ic_accessible_white_36px.xml from drawable resource ID #0x7f02004b at android.content.res.Resources.loadDrawable(Resources.java:1918) at android.content.res.TypedArray.getDrawable(TypedArray.java:601) at android.widget.TextView.(TextView.java:622) at android.support.v7.widget.AppCompatTextView.(AppCompatTextView.java:60) at android.support.v7.widget.AppCompatTextView.(AppCompatTextView.java:56) at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103) at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:963) at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1022) at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675) at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) at android.view.LayoutInflater.inflate(LayoutInflater.java:489) at android.view.LayoutInflater.inflate(LayoutInflater.java:396) at android.view.LayoutInflater.inflate(LayoutInflater.java:352) at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14) at android.app.Activity.performCreate(Activity.java:5008) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) at android.app.ActivityThread.access$600(ActivityThread.java:130) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method) Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #1: invalid drawable tag vector at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:877) at android.graphics.drawable.Drawable.createFromXml(Drawable.java:818) at android.content.res.Resources.loadDrawable(Resources.java:1915) at android.content.res.TypedArray.getDrawable(TypedArray.java:601) at android.widget.TextView.(TextView.java:622) at android.support.v7.widget.AppCompatTextView.(AppCompatTextView.java:60) at android.support.v7.widget.AppCompatTextView.(AppCompatTextView.java:56) at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103) at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:963) at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1022) at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675) at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) at android.view.LayoutInflater.inflate(LayoutInflater.java:489) at android.view.LayoutInflater.inflate(LayoutInflater.java:396) at android.view.LayoutInflater.inflate(LayoutInflater.java:352) at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14) at android.app.Activity.performCreate(Activity.java:5008) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) at android.app.ActivityThread.access$600(ActivityThread.java:130) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method) 

Comme il semble que Google ne fasse rien de plus rapidement sur ce problème, j’ai dû trouver une solution réutilisable plus solide pour toutes mes applications:

  1. Ajoutez d’abord des atsortingbuts TextView personnalisés dans le fichier attrs.xml de votre application “res / values ​​/ attrs.xml” :

             
  2. Ensuite, créez une classe TextView personnalisée comme ceci:

     import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v7.content.res.AppCompatResources; import android.support.v7.widget.AppCompatTextView; import android.util.AtsortingbuteSet; public class CustomTextView extends AppCompatTextView { public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AtsortingbuteSet attrs) { super(context, attrs); initAttrs(context, attrs); } public CustomTextView(Context context, AtsortingbuteSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); } void initAttrs(Context context, AtsortingbuteSet attrs) { if (attrs != null) { TypedArray atsortingbuteArray = context.obtainStyledAtsortingbutes( attrs, R.styleable.CustomTextView); Drawable drawableStart = null; Drawable drawableEnd = null; Drawable drawableBottom = null; Drawable drawableTop = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { drawableStart = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableStartCompat); drawableEnd = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableEndCompat); drawableBottom = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableBottomCompat); drawableTop = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableTopCompat); } else { final int drawableStartId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableStartCompat, -1); final int drawableEndId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableEndCompat, -1); final int drawableBottomId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableBottomCompat, -1); final int drawableTopId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableTopCompat, -1); if (drawableStartId != -1) drawableStart = AppCompatResources.getDrawable(context, drawableStartId); if (drawableEndId != -1) drawableEnd = AppCompatResources.getDrawable(context, drawableEndId); if (drawableBottomId != -1) drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId); if (drawableTopId != -1) drawableTop = AppCompatResources.getDrawable(context, drawableTopId); } // to support rtl setCompoundDrawablesRelativeWithInsortingnsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom); atsortingbuteArray.recycle(); } } } 
  3. Maintenant, vous pouvez l’utiliser facilement dans n’importe quelle disposition en fonction de vos atsortingbuts personnalisés:

      app:drawableEndCompat="@drawable/your_vector_drawable"  app:drawableTopCompat="@drawable/your_vector_drawable"  app:drawableBottomCompat="@drawable/your_vector_drawable"  /> 
    • Vous pouvez faire la même chose avec Button , EditText et RadioButton car ils dérivent de TextView

J’espère que cela t’aides 🙂

Cette solution n’est plus correcte. A partir de la version 23.3.0, les fichiers vectoriels tirables ne peuvent être chargés que via l’application: srcCompat ou setImageResource ()

Essayez d’envelopper votre vecteur dans une liste de calques ou un sélecteur:

  

ic_accessible_white_wrapped.xml:

    

Le meilleur moyen que j’ai trouvé:

 Drawable leftDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_search); search.setCompoundDrawablesWithInsortingnsicBounds(leftDrawable, null, null, null); 

Pour compléter certaines des réponses ici: vous pouvez obtenir que VectorDrawable fonctionne comme drawableLeft (etc.), mais cela dépend de la version de la bibliothèque de support et son prix est bon.

Dans quels cas fonctionne-t-il? J’ai fait ce diagramme pour aider (valable pour la bibliothèque de support 23.4.0 à – au moins – 25.1.0).

Cheatsheet VectorDrawable

Aucune des autres réponses n’a fonctionné, voici comment j’ai ajouté VectorDrawable à un TextView , vous devez utiliser VectorDrawableCompat.create() pour traiter VectorDrawables ci-dessous Android L :

 TextView titleTextView = (TextView) viewHolder.getView(android.R.id.text1); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Drawable leftDrawable = AppCompatResources .getDrawable(context, R.drawable.ic_tickbox); titleTextView.setCompoundDrawablesWithInsortingnsicBounds(leftDrawable, null, null, null); } else { //Safely create our VectorDrawable on pre-L android versions. Drawable leftDrawable = VectorDrawableCompat .create(context.getResources(), R.drawable.ic_tickbox, null); titleTextView.setCompoundDrawablesWithInsortingnsicBounds(leftDrawable, null, null, null); } 

Bref, doux et au point!

De Google: Comme pour Android Support Library 23.3.0, les fichiers vectoriels supportables ne peuvent être chargés que via l’application: srcCompat ou setImageResource ().

http://android-developers.blogspot.ru/2016/02/android-support-library-232.html

Il est possible de définir directement des éléments vectoriels dans XML, mais vous devez inclure le cadre de liaison de données.

Ecrivez

  

et envelopper toute votre mise en page dans une , donc en gros votre xml ressemblerait à ceci:

       

Pour activer le cadre de liaison de données, ajoutez simplement

 android { .... defaultConfig { dataBinding { enabled = true } } } 

Vous n’avez pas besoin d’utiliser d’autres fonctionnalités de la bibliothèque de liaison

MODIFIER:

Bien sûr, si vous voulez utiliser des fichiers vectoriels pré-Lollipop, vous devez activer les fichiers vectoriels à l’aide du

vectorDrawables.useSupportLibrary = true

Donc, votre build.gradle besoin de 2 nouvelles commandes:

 android { .... defaultConfig { vectorDrawables.useSupportLibrary = true dataBinding { enabled = true } } } 

merci à rkmax pour la remarque

Je suis allé à travers toutes les réponses et en utilisant le dernier studio Android 3.0.1 et la bibliothèque de support appcompat 26.1.0 je peux assurer que cela fonctionne bien.

Dans le fichier build.gradle (app)

 android { comstackSdkVersion 26 defaultConfig { vectorDrawables.useSupportLibrary = true } } dependencies { implementation 'com.android.support:appcompat-v7:26.1.0' } 

Et dans Activity Extension, AppcompatActivity inclut ces méthodes externes, par exemple un bloc statique

 static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } 

ou si vous voulez que cela s’applique à l’ensemble de l’application, incluez simplement cette ligne dans la classe d’application qui étend la classe

 override fun onCreate() { super.onCreate() AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) } 

Textview en xml

    

account_drawableleft_selector.xml

      

Je suis tellement en retard pour répondre à cette question que je suis resté en retard avec ce problème. J’ai eu le même problème avec les tirables svg / vector avec TextView. Au lieu de créer votre propre dessin personnalisé, je suis en mesure de résoudre mon problème avec 2 lignes de code comme ci-dessous:

 Drawable drawableTop = AppCompatResources.getDrawable(view.getContext(), iconId); view.setCompoundDrawablesWithInsortingnsicBounds(null, drawableTop, null, null); 

J’espère que ça va vous aider.

Si vous utilisez la liaison, il existe une autre méthode magique pour utiliser la même approche pour utiliser des vecteurs dans un TextView. Les envelopper comme:

 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 étudié ce qui se passe en coulisse, mais je suppose que TextView utilise la méthode getDrawable de AppCompatResources ou similaire.

J’ai conçu une minuscule bibliothèque pour cela – textview-rich-drawable (elle permet également de définir la taille et la teinte des éléments à dessiner).

  

Et la dépendance

 comstack 'com.tolstykh.textviewrichdrawable:textview-rich-drawable:0.3.2' 

entrer la description de l'image ici

Dans le fichier build.gradle (app)

 android { comstackSdkVersion 26 defaultConfig { vectorDrawables.useSupportLibrary = true } dataBinding { enabled = true } } public class BindingUtils { @BindingAdapter("android:drawableRight") public static void setDrawableStart(TextView textView, int resourceId) { Drawable drawable = AppCompatResources.getDrawable(textView.getContext(), resourceId); Drawable[] drawables = textView.getCompoundDrawables(); textView.setCompoundDrawablesWithInsortingnsicBounds(drawable, drawables[1], drawables[2], drawables[3]); } } 

utiliser (lors de la liaison de données)

 android:drawableRight="@{viewModel.ResId}" 

Ou (normal)

 android:drawableRight="@{@drawable/ic_login_24dp}" 

Sur la base de la réponse de Behzad Bahmanyar, j’ai remarqué que je ne pouvais pas utiliser les atsortingbuts normaux d’android pour les fichiers png normaux:

 android:drawableTop android:drawableBottom etc 

car il serait remplacé par null dans

 Drawable drawableTop = null; ... setCompoundDrawablesRelativeWithInsortingnsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom); 

si l’ app:drawableTopCompat n’était pas définie, mais android:drawableTop était (par exemple).

Voici la solution complète:

 public class CustomTextView extends AppCompatTextView { private static final int NOT_SET = -1; private static final int LEFT = 0; private static final int START = 0; private static final int TOP = 1; private static final int RIGHT = 2; private static final int END = 2; private static final int BOTTOM = 3; public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AtsortingbuteSet attrs) { super(context, attrs); initAttrs(context, attrs); } public CustomTextView(Context context, AtsortingbuteSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); } void initAttrs(Context context, AtsortingbuteSet attrs) { if (attrs == null) { return; } Drawable[] drawablesArr = getCompoundDrawables(); TypedArray atsortingbuteArray = context.obtainStyledAtsortingbutes(attrs, R.styleable.CustomTextView); Drawable drawableStart = null; Drawable drawableEnd = null; Drawable drawableBottom = null; Drawable drawableTop = null; Drawable drawableLeft = null; Drawable drawableRight = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { drawableStart = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableStartCompat); drawableEnd = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableEndCompat); drawableBottom = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableBottomCompat); drawableTop = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableTopCompat); drawableLeft = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableLeftCompat); drawableRight = atsortingbuteArray.getDrawable(R.styleable.CustomTextView_drawableRightCompat); } else { final int drawableStartId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableStartCompat, NOT_SET); final int drawableEndId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableEndCompat, NOT_SET); final int drawableBottomId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableBottomCompat, NOT_SET); final int drawableTopId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableTopCompat, NOT_SET); final int drawableLeftId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableLeftCompat, NOT_SET); final int drawableRightId = atsortingbuteArray.getResourceId(R.styleable.CustomTextView_drawableRightCompat, NOT_SET); if (drawableStartId != NOT_SET) drawableStart = AppCompatResources.getDrawable(context, drawableStartId); if (drawableLeftId != NOT_SET) drawableLeft = AppCompatResources.getDrawable(context, drawableLeftId); if (drawableEndId != NOT_SET) drawableEnd = AppCompatResources.getDrawable(context, drawableEndId); if (drawableRightId != NOT_SET) drawableRight = AppCompatResources.getDrawable(context, drawableRightId); if (drawableBottomId != NOT_SET) drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId); if (drawableTopId != NOT_SET) drawableTop = AppCompatResources.getDrawable(context, drawableTopId); } drawableStart = (drawableStart != null ? drawableStart : drawablesArr[START]); drawableLeft = (drawableLeft != null ? drawableLeft : drawablesArr[LEFT]); drawableStart = (drawableStart != null ? drawableStart : drawableLeft); drawableEnd = (drawableEnd != null ? drawableEnd : drawablesArr[END]); drawableRight = (drawableRight != null ? drawableRight : drawablesArr[RIGHT]); drawableEnd = (drawableEnd != null ? drawableEnd : drawableRight); drawableBottom = (drawableBottom != null ? drawableBottom : drawablesArr[BOTTOM]); drawableTop = (drawableTop != null ? drawableTop : drawablesArr[TOP]); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { setCompoundDrawablesRelativeWithInsortingnsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom); } else { setCompoundDrawables(drawableStart, drawableTop, drawableEnd, drawableBottom); } atsortingbuteArray.recycle(); } }