¿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:
- Problemas de procesamiento Excepción android.graphics.drawable
- Cargar un vector dibujable en la vista de la imagen desde la tarjeta sd
- Coracteres corrompidos o desaparecidos después de ejecutar Proguard
- Recursos de VectorDrawableCompat $ NotFoundException en KitKat y más abajo
- Android VectorDrawable como dibujos compuestos
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?
- Biblioteca de soporte de Android: getDrawable independiente si vector o no
- Android vectorDrawables.useSupportLibrary = true está deteniendo la aplicación
- Control preciso sobre las animaciones de Androids VectorDrawable
- ¿Por qué mi SVG no se carga en Vector Asset Studio
- Vector dibujable no dibujado correctamente en Android Studio
- Descripción de las propiedades VectorDrawable de Android
- ¿Cómo implementar animated vector drawables usando la biblioteca de soporte de diseño 23.2?
- Android vector drawable para el icono del lanzador y otras imágenes en Android N
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 deAppCompat
vectoriales cuando se hace referencia en otro contenedorStateListDrawable
comoStateListDrawable
,InsetDrawable
,LayerDrawable
,LevelListDrawable
yRotateDrawable
. Mediante el uso de esta indirección, puede utilizar vector drawables en casos tales como elTextView
android:drawableLeft
TextView
deTextView
, 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).
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));