Cambiar el color de relleno en el activo del vector en Android Studio

169

Android Studio ahora admite activos vectoriales en 21+ y generará pngs para versiones inferiores en tiempo de compilación. Tengo un activo vectorial (de los iconos de material) que quiero cambiar el color de relleno. Esto funciona en 21+, pero los png generados no cambian de color. ¿Hay alguna forma de hacer esto?

<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>

Patricio
fuente

Respuestas:

333

No edite los activos vectoriales directamente. Si está utilizando un vector dibujable en un ImageButton, simplemente elija su color android:tint.

<ImageButton
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:id="@+id/button"
        android:src="@drawable/ic_more_vert_24dp"
        android:tint="@color/primary" />
AAAA-MM-DD
fuente
24
tiñendo sólo funciona en más de 21 dispositivos, ¿tienes alguna sugerencia para dispositivos pre-lollipop
mudit
12
android: tint funciona en todas las versiones de Android desde APIv1. Lo que quieres decir es drawableTint.
AAAA-MM-DD
31
android:tintdebe ser despuésandroid:src
EmmanuelMess
55
¿Qué hay de drawableLeftadentro Button?
Pratik Butani
8
@mudit intente usar un vector con fillColor = "# colorvalue", no use una referencia de color @ porque solo funcionan SDK 21+ para vectores (así que no para los PNG generados)
PieterAelse
95

Puedes hacerlo.

PERO no puede usar referencias de color para colores (..lame), de lo contrario funcionará solo para L +

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
<path
    android:fillColor="#FFAABB"
    android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zm-6,0C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>

urSus
fuente
11
¡Esta debería ser la respuesta aceptada! Las referencias de @color no funcionan en vectores anteriores a Lollipop (por lo tanto, vector -> conversión PNG) code.google.com/p/android/issues/detail?id=186431
PieterAelse
55
Las referencias @color ahora se pueden usar para el atributo fillColor para todas las versiones de Android, sin embargo, no admite listas de estado de color.
TheIT
Parece que la forma de hacer listas de estados vectoriales es con AnimatedStateListDrawable s
gMale
1
@TheIT ¿Qué tengo que habilitar? No parece funcionar para mí
urSus
@PieterAelse No estoy seguro, ¿qué pasa si desea utilizar el mismo activo pero con diferentes fondos (tintes como en la respuesta anterior). En su solución, tendrá varias instancias del mismo recurso pero con un color de relleno diferente
Anton Makov
71

Como se dijo en otras respuestas, no edite el vector dibujable directamente, en su lugar, puede teñir el código java, así:

    mWrappedDrawable = mDrawable.mutate();
    mWrappedDrawable = DrawableCompat.wrap(mWrappedDrawable);
    DrawableCompat.setTint(mWrappedDrawable, mColor);
    DrawableCompat.setTintMode(mWrappedDrawable, PorterDuff.Mode.SRC_IN);

Y en aras de la simplicidad, he creado una clase auxiliar:

import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

/**
 * {@link Drawable} helper class.
 *
 * @author Filipe Bezerra
 * @version 18/01/2016
 * @since 18/01/2016
 */
public class DrawableHelper {
    @NonNull Context mContext;
    @ColorRes private int mColor;
    private Drawable mDrawable;
    private Drawable mWrappedDrawable;

    public DrawableHelper(@NonNull Context context) {
        mContext = context;
    }

    public static DrawableHelper withContext(@NonNull Context context) {
        return new DrawableHelper(context);
    }

    public DrawableHelper withDrawable(@DrawableRes int drawableRes) {
        mDrawable = ContextCompat.getDrawable(mContext, drawableRes);
        return this;
    }

    public DrawableHelper withDrawable(@NonNull Drawable drawable) {
        mDrawable = drawable;
        return this;
    }

    public DrawableHelper withColor(@ColorRes int colorRes) {
        mColor = ContextCompat.getColor(mContext, colorRes);
        return this;
    }

    public DrawableHelper tint() {
        if (mDrawable == null) {
            throw new NullPointerException("É preciso informar o recurso drawable pelo método withDrawable()");
        }

        if (mColor == 0) {
            throw new IllegalStateException("É necessário informar a cor a ser definida pelo método withColor()");
        }

        mWrappedDrawable = mDrawable.mutate();
        mWrappedDrawable = DrawableCompat.wrap(mWrappedDrawable);
        DrawableCompat.setTint(mWrappedDrawable, mColor);
        DrawableCompat.setTintMode(mWrappedDrawable, PorterDuff.Mode.SRC_IN);

        return this;
    }

    @SuppressWarnings("deprecation")
    public void applyToBackground(@NonNull View view) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            view.setBackground(mWrappedDrawable);
        } else {
            view.setBackgroundDrawable(mWrappedDrawable);
        }
    }

    public void applyTo(@NonNull ImageView imageView) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        imageView.setImageDrawable(mWrappedDrawable);
    }

    public void applyTo(@NonNull MenuItem menuItem) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        menuItem.setIcon(mWrappedDrawable);
    }

    public Drawable get() {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        return mWrappedDrawable;
    }
}

Para usar solo haga lo siguiente:

    DrawableHelper
            .withContext(this)
            .withColor(R.color.white)
            .withDrawable(R.drawable.ic_search_24dp)
            .tint()
            .applyTo(mSearchItem);

O:

    final Drawable drawable = DrawableHelper
            .withContext(this)
            .withColor(R.color.white)
            .withDrawable(R.drawable.ic_search_24dp)
            .tint()
            .get();

    actionBar.setHomeAsUpIndicator(drawable);
Filipe Bezerra de Sousa
fuente
Hola Filipe, gracias por tu respuesta. ¿Tiene una biblioteca, código github recortado donde podemos ver la licencia? gracias :)
Vincent D.
2
No Vicent, no hay licencia en absoluto. La solución es tan simple que supongo que el patrón Builder utilizado aquí no es necesario. Pero cualquiera puede beneficiarse de esta solución y usarla sin licencia.
Filipe Bezerra de Sousa
¡Gran respuesta! Funciona exactamente como lo necesito
Eoin
1
@VincentD. El pie de página de SO dice "contribuciones de usuarios con licencia bajo cc by-sa 3.0 con atribución requerida"
shelll
A mí me funcionó con algunos cambios. Gracias por tu ayuda.
André Luiz Reis
36

Para cambiar el color de la imagen vectorial puede usar directamente android: tint = "@ color / colorAccent"

<ImageView
        android:id="@+id/ivVectorImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_account_circle_black_24dp"
        android:tint="@color/colorAccent" />

Para cambiar el color programáticamente

ImageView ivVectorImage = (ImageView) findViewById(R.id.ivVectorImage);
ivVectorImage.setColorFilter(getResources().getColor(R.color.colorPrimary));
Rana Ranvijay Singh
fuente
getColor () está en desuso
David
¿Cómo usarlo para *** dibujable de TextView?
Hemant Kaushik
getColor (ResId) está en desuso @David, pero getColor(ResId, Theme)no lo está. O puede usarlo ResourcesCompat.getColor(getResources(), R.color.primary, null);si no le importa el tema ... o si su delegado de contexto / política ES una actividad, puede hacerlo getTheme()para ese último parámetro.
Martin Marconcini
15

Actualmente la solución de trabajo es android: fillColor = "# FFFFFF"

Nada funcionó para mí excepto la codificación en el vector

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
      android:fillColor="#FFFFFF"
    android:viewportHeight="24.0">
<path
    android:fillColor="#FFFFFF"
    android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zm-6,0C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>

Sin embargo, fillcolor y tint podrían funcionar pronto. Por favor vea esta discusión para más información:

https://code.google.com/p/android/issues/detail?id=186431

Además, los colores pueden permanecer en el caché, por lo que puede ser útil eliminar la aplicación para todos los usuarios.

sivi
fuente
7

Android Studio ahora admite vectores pre-lollipop. Sin conversión PNG. Todavía puede cambiar su color de relleno y funcionará.

En su ImageView, use

 app:srcCompat="@drawable/ic_more_vert_24dp"

En tu archivo gradle,

 // Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
   }  
 }  

 compile 'com.android.support:design:23.4.0'
Sayooj Valsan
fuente
10
La pregunta es "cómo cambiar el color de relleno del vector", no "cómo usar el activo del vector"
Leo Droidcoder
5

Actualización: AppCompatsoporte

Otras respuestas que sospechan android:tintque solo funcionarán en más de 21 dispositivos, AppCompat ( v23.2.0 y superior ) ahora ofrece un manejo compatible con versiones anteriores del atributo tint.

Entonces, el curso de acción sería usar AppCompatImageViewy app:srcCompat(en el espacio de nombres de AppCompat) en lugar de android:src(espacio de nombres de Android).

Aquí hay un ejemplo (AndroidX: Esto es androidx.appcompat.widget.AppCompatImageView ;)):

<android.support.v7.widget.AppCompatImageView
        android:id="@+id/credits_material_icon"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:scaleType="fitCenter"
        android:tint="#ffd2ee"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:srcCompat="@drawable/ic_dollar_coin_stack" />

Y no olvide habilitar el soporte de dibujo vectorial en gradle:

vectorDrawables.useSupportLibrary = true 
Manish Kumar Sharma
fuente
Solo una actualización. Hoy en día AppCompatImageViewestá bajoandroidx.appcompat.widget.AppCompatImageView
Roc Boronat
2

Agregue esta biblioteca a Gradle para habilitar el vector de color dibujable en dispositivos Android antiguos.

compile 'com.android.support:palette-v7:26.0.0-alpha1'

y volver a sincronizar gradle. Creo que resolverá el problema.

Siddhartha Maji
fuente
2

Si los vectores no muestran colores configurados individualmente con fillColor, entonces pueden estar configurados en un parámetro de widget predeterminado.

Intente agregar app:itemIconTint="@color/lime"a activity_main.xml para establecer un tipo de color predeterminado para los iconos del widget.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:itemIconTint="@color/lime"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

VectorDrawable @ developers.android

lubi
fuente
En Android Studio 3.6, cambie en svg xml este campo: android: fillColor = "# FFFFC400"
a_subscriber el
1

si buscas soportar la versión anterior pre lolipop

usa el mismo código xml con algunos cambios

en lugar de lo normal ImageView --> AppCompatImageView

en vez de android:src --> app:srcCompat

aquí hay un ejemplo

<android.support.v7.widget.AppCompatImageView
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:id="@+id/button"
        app:srcCompat="@drawable/ic_more_vert_24dp"
        android:tint="@color/primary" />

no te olvides de actualizar tu gradle como @ Sayooj Valsan menciona

// Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
   }  
 }  

 compile 'com.android.support:design:23.4.0'

Aviso Para cualquiera que use el vector, nunca le dé su referencia de vector a un color como este, android:fillColor="@color/primary"déle su valor hexadecimal.

Mina Fawzy
fuente
¿Por qué nunca usar @colorpara fillcolor?
HoseinIT
0

Para aquellos que no usan un ImageView, lo siguiente funcionó para mí en un plano View(y, por lo tanto, el comportamiento debería replicarse en cualquier tipo de vista)

<View
    android:background="@drawable/ic_reset"
    android:backgroundTint="@color/colorLightText" />
Bonton255
fuente