¿Es posible usar VectorDrawable en Botones y TextViews usando android: DrawableRight?

Cuando uso VectorDrawable activos en un textview o imageview consigo un accidente de ejecución cuando se utiliza "android: DrawableRight" / "android: DrawableEnd" / "android: DrawableStart" / "android: DrawableLeft".

La aplicación compilará bien sin advertencias.

estoy usando

  • Gradle 1.5
  • Biblioteca de soporte 23.2 ('com.android.support:appcompat-v7:23.2.0')

Lo que he encontrado sin embargo es que puedo asignar programaticamente SVG en Java sin accidentes como este.

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

(Sospecho que esto es un error de biblioteca de soporte para 23.2.)

¿Pero es posible usar drawableRight etc para los activos de SVG?

Aquí está mi diseño

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="au.com.angryitguy.testsvg.MainActivity"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableRight="@drawable/ic_accessible_white_36px" android:background="@color/colorPrimary" android:textColor="#FFFFFF" android:textSize="22sp" android:text="Hello World!"/> </RelativeLayout> 

Aquí está mi actividad

 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); } } 

Aquí está el activo VectorDrawable no modificado del sitio de diseño de materiales de Google.

 <vector android:height="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#FFFFFF" android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/> <path android:fillColor="#FFFFFF" android:pathData="M19,13v-2c-1.54,0.02 -3.09,-0.75 -4.07,-1.83l-1.29,-1.43c-0.17,-0.19 -0.38,-0.34 -0.61,-0.45 -0.01,0 -0.01,-0.01 -0.02,-0.01L13,7.28c-0.35,-0.2 -0.75,-0.3 -1.19,-0.26C10.76,7.11 10,8.04 10,9.09L10,15c0,1.1 0.9,2 2,2h5v5h2v-5.5c0,-1.1 -0.9,-2 -2,-2h-3v-3.45c1.29,1.07 3.25,1.94 5,1.95zM12.83,18c-0.41,1.16 -1.52,2 -2.83,2 -1.66,0 -3,-1.34 -3,-3 0,-1.31 0.84,-2.41 2,-2.83L9,12.1c-2.28,0.46 -4,2.48 -4,4.9 0,2.76 2.24,5 5,5 2.42,0 4.44,-1.72 4.9,-4h-2.07z"/> </vector> 

Aquí está mi aplicación build.gradle

 apply plugin: 'com.android.application' android { compileSdkVersion 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 attribute ids around aaptOptions { additionalParameters "--no-version-vectors" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.0' } 

Aquí está el accidente. (Observe los errores de inflar que hacen referencia a la vista de texto).

 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.<init>(TextView.java:622) at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:60) at android.support.v7.widget.AppCompatTextView.<init>(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.<init>(TextView.java:622) at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:60) at android.support.v7.widget.AppCompatTextView.<init>(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) 

Debido a que parece que Google no va a hacer nada sobre este problema en el corto plazo, tuve que encontrar una solución reutilizable más sólida para todas mis aplicaciones:

  1. Primero agregue atributos personalizados de TextView en el archivo attrs.xml de su aplicación "res / values ​​/ attrs.xml" :

     <resources> <declare-styleable name="CustomTextView"> <attr name="drawableLeftCompat" format="reference"/> <attr name="drawableRightCompat" format="reference"/> <attr name="drawableTopCompat" format="reference"/> <attr name="drawableBottomCompat" format="reference"/> </declare-styleable> </resources> 
  2. A continuación, cree una clase personalizada de TextView como ésta:

     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.AttributeSet; public class CustomTextView extends AppCompatTextView { public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(context, attrs); } public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); } void initAttrs(Context context, AttributeSet attrs) { if (attrs != null) { TypedArray attributeArray = context.obtainStyledAttributes( attrs, R.styleable.CustomTextView); Drawable drawableLeft = null; Drawable drawableRight = null; Drawable drawableBottom = null; Drawable drawableTop = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { drawableLeft = attributeArray.getDrawable(R.styleable.CustomTextView_drawableLeftCompat); drawableRight = attributeArray.getDrawable(R.styleable.CustomTextView_drawableRightCompat); drawableBottom = attributeArray.getDrawable(R.styleable.CustomTextView_drawableBottomCompat); drawableTop = attributeArray.getDrawable(R.styleable.CustomTextView_drawableTopCompat); } else { final int drawableLeftId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableLeftCompat, -1); final int drawableRightId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableRightCompat, -1); final int drawableBottomId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableBottomCompat, -1); final int drawableTopId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableTopCompat, -1); if (drawableLeftId != -1) drawableLeft = AppCompatResources.getDrawable(context, drawableLeftId); if (drawableRightId != -1) drawableRight = AppCompatResources.getDrawable(context, drawableRightId); if (drawableBottomId != -1) drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId); if (drawableTopId != -1) drawableTop = AppCompatResources.getDrawable(context, drawableTopId); } setCompoundDrawablesWithIntrinsicBounds(drawableLeft, drawableTop, drawableRight, drawableBottom); attributeArray.recycle(); } } } 
  3. Ahora puedes usarlo fácilmente en cualquier diseño por tus atributos personalizados:

     <YOUR_VIEW_PACKAGE.CustomTextView android:id="@+id/edt_my_edit_text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:drawableLeftCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableRightCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableTopCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableBottomCompat="@drawable/your_vector_drawable" <!-- vector drawable --> /> 
    • Puede hacer lo mismo con Button , EditText y RadioButton porque derivan de TextView

Espero que esto ayude 🙂

Esta solución ya no es correcta. A partir de la versión 23.3.0, el vector drawables sólo se puede cargar mediante app: srcCompat o setImageResource ()

Trate de envolver su vector dibujable en lista de capas o selector:

 <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:drawableRight="@drawable/ic_accessible_white_wrapped" android:background="@color/colorPrimary" android:textColor="#FFFFFF" android:textSize="22sp" android:text="Hello World!"/> 

Ic_accessible_white_wrapped.xml:

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

La mejor manera que encontré:

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

Para complementar algunas de las respuestas aquí: puede obtener VectorDrawable para trabajar como drawableLeft (etc), pero depende de la versión de la biblioteca de soporte y viene con un precio.

¿En qué casos funciona? Hice este diagrama para ayudar (válido para la biblioteca de la ayuda 23.4.0 a – por lo menos – 25.1.0).

VectorDrawable cheatsheet

Desde Google: A partir de Android Support Library 23.3.0, el soporte vectorial drawables solo se puede cargar mediante app: srcCompat o setImageResource ().

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

Si está utilizando el enlace, hay otra forma mágica de tener el mismo enfoque para utilizar los vectores en un TextView. Envolviéndolos como:

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

Eso funcionará mágicamente, no he investigado lo que está sucediendo detrás de las escenas, pero supongo que el TextView está usando el método getDrawable de AppCompatResources o similar.

Es posible establecer directamente dibujos vectoriales en xml, pero debe incluir el marco de vinculación de datos.

Solo escribe

 <TextView ... android:drawableRight="@{@drawable/ic_accessible_white_36px}"/> 

Y envolver todo su diseño en una etiqueta <layout> , por lo que básicamente su xml se vería así:

 <?xml version="1.0" encoding="utf-8"?> <layout> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="au.com.angryitguy.testsvg.MainActivity"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:drawableRight="@{@drawable/ic_accessible_white_36px}" android:text="Hello World!" android:textColor="#FFFFFF" android:textSize="22sp"/> </RelativeLayout> </layout> 

Para activar el marco de vinculación de datos simplemente agregue

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

No tiene que utilizar ninguna otra característica de la biblioteca de enlace

EDITAR:

Por supuesto, si quieres usar el vector drawables pre-Lollipop tu tienes que habilitar el soporte vectorial drawables utilizando

vectorDrawables.useSupportLibrary = true

Así que tu build.gradle necesita dos nuevos comandos:

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

Gracias a rkmax por la observación

Estoy muy tarde para responder a esta pregunta, ya que se metió hasta tarde con este problema. Tuve el mismo problema con svg / vector drawables con TextView. En lugar de hacer su propia costumbre drawable soy capaz de arreglar mi problema con 2 líneas de código como a continuación:

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

Espero que te ayude.

Ninguna de las otras respuestas funcionó, aquí es cómo he agregado un VectorDrawable a un TextView , usted debe utilizar VectorDrawableCompat.create() cuando se trata de VectorDrawables debajo de 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.setCompoundDrawablesWithIntrinsicBounds(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.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null); } 

¡Corto, dulce y al punto!

  • JSoup 1.6.0 en Android lanza Excepción: String.isEmpty () NoSuchMethodExists
  • Explicación del método getView () de un ArrayAdapter
  • Java.lang.NumberFormatException: Invalid int: ""
  • Compatibilidad con versiones anteriores del diseño del material: colorAccent requiere el nivel 21 de API cuando se utiliza appcompat7
  • Configuración de la configuración de proxy de Android mediante programación mediante el método System.Global
  • ActionBar no funciona al extender ListActivity
  • ¿Puede alguien ayudarme con Android RemoteControlClient?
  • ¿Ha ocurrido un error no autorizado 401 en la adaptación?
  • ¿Cómo se pueden manipular las salidas de variantes con el complemento Android Gradle 3.0.0+?
  • Creación de una biblioteca java con Eclipse
  • ¿Cómo guardar con seguridad un archivo en el disco en android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.