¿Cómo utilizar el vector drawables con vista además de ImageView con srcCompat?

app:srcCompat con ImageView permite el uso compatible con versiones anteriores de drawables vectoriales. Pero, ¿cómo puedes usarlos con otras View s además de ImageView ? Por ejemplo, los atributos TextView como android:drawableLeft .

También usando el vector drawable como android:icon con MenuItem causó un choque con la excepción siguiente:

 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) 

Con Support Library 23.2.0, ¿cómo se puede abordar este problema?

Para AppCompat versión 23.3.0 donde no hay solución de trabajo a través del selector XML (respuesta aceptada razzledazzle) podemos hacer esto por programación:

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

Este código es equivalente para este selector 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> 

ACTUALIZAR

Si el vector dibujable no se muestra utilizando API 23, tendrá que convertir el VectorDrawable a un Drawable normal en primer lugar. Si quieres usar setCompoundDrawablesWithIntrinsicBounds tendrás que hacer esto, pero para StateListDrawable no necesité.

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

Actualización 2 : Han añadido una opción para habilitarlo nuevamente en la Biblioteca de soporte 23.4.0:

Para los usuarios de AppCompat, hemos añadido una API opt-in para volver a habilitar el soporte Vector Drawables de los recursos (el comportamiento que se encuentra en 23.2) a través de AppCompatDelegate.setCompatVectorFromResourcesEnabled () – tenga en cuenta que esto todavía puede causar problemas con el uso de memoria y problemas Actualizando instancias de configuración, por lo que se deshabilita de forma predeterminada.

Actualización : Esto ya no funciona a partir de la versión 23.3.0

Para los usuarios de AppCompat, hemos decidido eliminar la funcionalidad que permite utilizar vector drawables de recursos en dispositivos pre-Lollipop debido a problemas encontrados en la implementación en la versión 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%5D . Uso de la aplicación: srcCompat y setImageResource () sigue funcionando.

Desde la publicación de Google+ de desarrolladores de Android


Uso de AppCompat y la aplicación: srcCompat es el método más infalible de integrar vector drawables en su aplicación.

Esa cita es de la blogpost oficial para el lanzamiento de la versión 23.2.0 de la Biblioteca de Soporte.

El post también menciona lo siguiente:

Encontrará referencias directas a elementos vectoriales fuera de la app:srcCompat fallará antes de Lollipop. Sin embargo, AppCompat admite la carga de AppCompat vectoriales cuando se hace referencia en otro contenedor StateListDrawable como StateListDrawable , InsetDrawable , LayerDrawable , LevelListDrawable y RotateDrawable . Mediante el uso de esta indirección, puede utilizar vector drawables en casos tales como el TextView android:drawableLeft TextView de TextView , que normalmente no sería capaz de soportar vector drawables.

Esto se traduce en los pasos siguientes:

Paso 1:

Cree o importe un recurso vectorial que necesite para la aplicación. Por ejemplo, se puede crear un vector dibujable para el icono de búsqueda y darle nombre ic_action_search_vector.xml

Paso 2:

Cree otro recurso extraíble de proxy para el vector dibujable previamente creado. Digamos que para el ic_action_search_vector.xml anterior, se puede crear StateListDrawable como un simple StateListDrawable que podría contener las líneas siguientes:

 <?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> 

Este paso se puede omitir si se ha hecho referencia al vector dibujable de otro recurso dibujable que se utilizará con su vista.

Paso 3:

Utilice el recurso ic_action_search.xml (aquí, ic_action_search.xml ) que hace referencia al vector ic_action_search_vector.xml ( ic_action_search_vector.xml ) en lugar del vector dibujable directamente. Para un menú, sería como:

 <item android:id="@+id/search" android:title="@string/search" android:icon="@drawable/ic_action_search" app:showAsAction="always"/> 

Esta es la solución a ese problema!

Vector drawables se puede utilizar antes de Lollipop en otros lugares que la app:srcCompat , pero viene con un precio.

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

Puede agregar Vector Drawable en TextView mediante programación. Hacer uso de VectorDrawableCompat para añadir drawableLeft / drawableRight / drawableTop / drawableBottom / drawableStart / drawableEnd.

Pasos:

yo. Si TextView está dentro Actividad:

 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á dentro de Fragmento:

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

Para obtener más información sobre VectorDrawableCompat, consulte este enlace

Android 5.0 (API nivel 21) y superior proporciona soporte vectorial extraíble. Si su aplicación tiene un nivel mínimo API que es menor, Vector Asset Studio agrega el archivo vectorial dibujable a su proyecto; También, en el tiempo de construcción, Gradle crea imágenes ráster PNG en varias resoluciones. Gradle genera las densidades PNG especificadas por la propiedad Densidad de lenguaje específico de dominio (DSL) generada en un archivo build.gradle. Para generar PNG, el sistema de compilación requiere el complemento de Android para Gradle 1.5.0 o superior.

Esto no es cierto si se incluye en su gradle vectorDrawables.useSupportLibrary = true

Defina como false o quite la línea completamente y todos sus vectores funcionarán como estaban. Pero para las versiones de los ancianos de Android que será capaz de confiar en el PNG convertido

Estoy usando una nueva biblioteca de soporte y todo lo que tengo que hacer es:

 compile 'com.android.support:appcompat-v7:25.1.1' 

En el archivo Build.gradle

  defaultConfig { vectorDrawables.useSupportLibrary = true } 

Ahora, donde quiera que estés usando como fragmento, actividad o adaptador, usa esto como la primera línea de tu clase

 static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } 

Después de que el uso como lo hacemos antes, something.xml

 <ImageView android:id="@+id/ivMainNavigationIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" /> 

Something.java

 thumbIcon.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.ic_check_circle_black_24dp)); 

O si tiene que tener una identificación dinámica que se debe establecer dinámicamente

 thumbIcon.setImageDrawable(ContextCompat.getDrawable(context,drawableID)); 
  • La función Auto Mirroring for RTL no funciona en las versiones de Android inferiores a 6.0
  • Android Robolectric y elementos decorativos vectoriales
  • ¿Puedo usar un vector dibujable de la misma manera que usé un parche 9?
  • AppCompatDrawableManager.get () vs VectorDrawableCompat.create ()
  • Android Vector Drawable <defs> no es compatible. ¿Como arreglarlo?
  • Google Play: necesitas comprobar el icono dentro de tu APK porque no es válido
  • Biblioteca de soporte VectorDrawable Resources $ NotFoundException
  • Youtube Play / pausa Animated Vector Drawable en android
  • ¿Cómo animar un VectorDrawable de una manera fluida-como?
  • TileMode repetir con vector drawable
  • VectorDrawable no se representa correctamente en API 23
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.