Cambiar el color dibujable mediante programación

139

Estoy tratando de cambiar el color de una imagen de marcador blanco por código. He leído que el siguiente código debería cambiar el color, pero mi marcador sigue siendo blanco.

Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY )

¿Me he perdido algo? ¿Hay alguna otra forma de cambiar los colores en mis elementos dibujables ubicados en mi carpeta res?

Johan
fuente
la respuesta aceptada no funcionó para mí ... usé esto Cómo responder [1], [1]: stackoverflow.com/questions/5940825/…
sham.y
Creo que todas las respuestas aquí cambian el color de fondo, pero no el color de la imagen. Estoy en lo cierto? ¿Puede alguien decirme por favor? Intenté todas las soluciones aquí y también sobre las mismas preguntas sobre stackoverflow, pero solo cambian el color de fondo en muchos casos. Así que creo que solo podemos cambiar el color de fondo, pero no el color de las imágenes. Estoy en lo cierto?
Shirish Herwade

Respuestas:

258

Prueba esto:

Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, R.drawable.my_drawable); 
Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
DrawableCompat.setTint(wrappedDrawable, Color.RED);    

El uso DrawableCompates importante porque proporciona compatibilidad con versiones anteriores y correcciones de errores en dispositivos API 22 y anteriores.

ρяσѕρєя K
fuente
Hmm, el color sigue siendo blanco. ¿Podría tener que ver con la OverlayItemsclase hello mapview que podría estar causando el problema? Es un sorteo regular de mi carpeta res, nada especial ...
Johan
Entonces, ¿cuál fue la solución?
speedynomads
@ ρяσѕρєяK eres muy impresionante. muy útil
luttu android
30
Es posible que prefiera PorterDuff.Mode.SRC_IN si desea que funcione con una gama más amplia de colores de origen.
Lorne Laliberte
1
El constructor PorterDuffColorFilter toma el formato de color ARGB
RichX
124

Puedes probar esto para svg vector drawable

DrawableCompat.setTint(
    DrawableCompat.wrap(myImageView.getDrawable()),
    ContextCompat.getColor(context, R.color.another_nice_color)
);
amorenew
fuente
44
La mejor manera que he visto para svg.
APSTRK
1
prefiero esto a la respuesta aceptada, aunque ambas funcionarán, pero con esta no tengo que preocuparme por qué dibujable configurar, solo obtengo la que ya está allí, y también es compatible con versiones anteriores, ¡genial!
RJFares
1
¡La mejor respuesta cuando nada funcionaba, funcionaba como un encanto! ¡Muchas gracias! Nota: También funciona cuando tiene un xml dibujable en su imageView / AppCompatImageView
Sjd
1
¿Cómo eliminarlo programáticamente?
Hardik Joshi
1
@HardikJoshi Documentation dice: Para borrar el tinte, pase nullaDrawable#setTintList(ColorStateList)
arekolek el
23

Es posible que deba llamar a mutate () en el dibujo o, de lo contrario, todos los iconos se verán afectados.

Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_my_icon).mutate();
TypedValue typedValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.colorIcon, typedValue, true);
icon.setColorFilter(typedValue.data, PorterDuff.Mode.SRC_ATOP);
shicky
fuente
21

Otra forma de hacer esto en Lollipop, Android 5. + es configurar un tinte en un mapa de bits dibujable como este:

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_back"
    android:tint="@color/red_tint"/>

Esto funcionará para usted si tiene una cantidad limitada de colores que desea usar en sus elementos dibujables. Mira mi blog para más información .

MinceMan
fuente
2
¡Agradable! Por cierto, esto parece funcionar bien en pre-Lollipop también. (Acabo de probar esto con un minSdkVersion 16dispositivo Android 4.1.1.)
Jonik
Al crear un mapa de bits de esta manera, no se estira para ajustarse al diseño como lo haría al usarlo android:background="...". ¡Bastante extraño!
Príncipe
Creo que es porque no estás creando un parche nueve aquí.
MinceMan
Lo sentimos, esta página no existe = (
Phan Van Linh
@ Jonik Las respuestas en su pregunta proporcionada son irrelevantes. Esta pregunta es la forma de cambiar el color de Drawable , no ImageView.
Antony.H
19

Puedes probar esto para ImageView. utilizando setColorFilter().

imageViewIcon.setColorFilter(ContextCompat.getColor(context, R.color.colorWhite));
Jaydip Meghapara
fuente
10

He escrito una función genérica en la que puede pasar el contexto, el ícono es id dibujable / ícono de imagen mipmap y el nuevo color que necesita para ese ícono.

Esta función devuelve un dibujable.

public static Drawable changeDrawableColor(Context context,int icon, int newColor) {
    Drawable mDrawable = ContextCompat.getDrawable(context, icon).mutate(); 
    mDrawable.setColorFilter(new PorterDuffColorFilter(newColor, PorterDuff.Mode.SRC_IN)); 
    return mDrawable;
} 

changeDrawableColor(getContext(),R.mipmap.ic_action_tune, Color.WHITE);
Sachin Tanpure
fuente
9

Puede probar un ColorMatrixColorFilter, ya que su color clave es blanco:

// Assuming "color" is your target color
float r = Color.red(color) / 255f;
float g = Color.green(color) / 255f;
float b = Color.blue(color) / 255f;

ColorMatrix cm = new ColorMatrix(new float[] {
        // Change red channel
        r, 0, 0, 0, 0,
        // Change green channel
        0, g, 0, 0, 0,
        // Change blue channel
        0, 0, b, 0, 0,
        // Keep alpha channel
        0, 0, 0, 1, 0,
});
ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);
myDrawable.setColorFilter(cf);
tiguchi
fuente
7

Esto funcionó para mí. Asegúrese de poner "ff" entre 0x y el código de color. Me gusta esto 0xff2196F3

Drawable mDrawable = ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_vector_home);
                    mDrawable.setColorFilter(new
                            PorterDuffColorFilter(0xff2196F3,PorterDuff.Mode.SRC_IN));
Bek
fuente
Hola @Bek, bienvenido a stackoverflow. Si esto funcionó para usted, sería muy útil incluir un jsfiddle con una solución mínima para mostrarlo. Ayudará a la persona que publicó la pregunta a comprender correctamente.
Arjun Chaudhary
6

Igual que la respuesta aceptada pero un método de conveniencia más simple:

val myDrawable = ContextCompat.getDrawable(context, R.drawable.my_drawable)
myDrawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN)
setCompoundDrawablesWithIntrinsicBounds(myDrawable, null, null, null)

Tenga en cuenta que el código aquí es Kotlin.

CorayThan
fuente
3

Es posible que desee probar Mode.LIGHTENo Mode.DARKEN. Los Javadocs de Android son horribles para explicar lo que hacen los modos PorterDuff. Puedes echarles un vistazo aquí: PorterDuff | Androide

Sugiero mirar alrededor de Compositing en el sitio de Mozilla aquí. (No tienen todos los modos que tiene Android, pero tienen muchos de ellos)

sebsebmc
fuente
3

Use esto: para java

view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_OVER)

para Kotlin

view.background.setColorFilter(Color.parseColor("#343434"),PorterDuff.Mode.SRC_OVER)

puede usar PorterDuff.Mode.SRC_ATOP, si su fondo tiene esquinas redondeadas, etc.

Ravi.Dudi
fuente
1

Sintaxis

"your image name".setColorFilter("your context".getResources().getColor("color name"));

Ejemplo

myImage.setColorFilter(mContext.getResources().getColor(R.color.deep_blue_new));
Om Prakash Sharma
fuente
0

Esto es lo que hice:

public static Drawable changeDrawableColor(int drawableRes, int colorRes, Context context) {
    //Convert drawable res to bitmap
    final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableRes);
    final Bitmap resultBitmap = Bitmap.createBitmap(bitmap, 0, 0,
            bitmap.getWidth() - 1, bitmap.getHeight() - 1);
    final Paint p = new Paint();
    final Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(resultBitmap, 0, 0, p);

    //Create new drawable based on bitmap
    final Drawable drawable = new BitmapDrawable(context.getResources(), resultBitmap);
    drawable.setColorFilter(new
            PorterDuffColorFilter(context.getResources().getColor(colorRes), PorterDuff.Mode.MULTIPLY));
    return drawable;
}
Edwin
fuente
0

Simplemente use

    android:drawableTint="@color/primary_color"

en su archivo XML. Reemplace primary_color por color personalizado

Arvina Kori
fuente
0

Cree un método como este:

//CHANGE ICON COLOR
private void changeIconColor(Context context ,int drawable){
    Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, drawable);
    assert unwrappedDrawable != null;
    Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
    DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.colorAccent));
}

y úsalo como:

    changeIconColor(this,R.drawable.ic_home);
sana ebadi
fuente
0

La forma más fácil de hacerlo:

imageView.setColorFilter(Color.rgb(r, g b));

o

imageView.setColorFilter(Color.argb(a, r, g, b));

a, r, g, b: valores de color argb.

Anubhav
fuente
Esto solo funcionará si el OP hubiera estado usando imageViews en lugar de dibujables.
SowingFiber
0

Para aquellos que usan Kotlin, una función de extensión simple:

fun Drawable.tint(context: Context,  @ColorRes color: Int) {
    DrawableCompat.setTint(this, context.resources.getColor(color, context.theme))
}

y luego simplemente hacer

background.tint(context, R.color.colorPrimary)
Chapz
fuente