Cómo cambiar los colores de un Drawable en Android?

Estoy trabajando en una aplicación de Android, y tengo un dibujable que estoy cargando desde una imagen de origen. En esta imagen, me gustaría convertir todos los píxeles blancos a un color diferente, digamos azul, y luego almacenar en caché el objeto Drawable resultante para poder usarlo más adelante.

Entonces, por ejemplo, digo que tengo un archivo PNG de 20×20 que tiene un círculo blanco en el medio, y que todo lo que está fuera del círculo es transparente. ¿Cuál es la mejor manera de azul ese círculo blanco y almacenar en caché los resultados? ¿La respuesta cambia si quiero usar esa imagen de origen para crear varios Drawables nuevos (por ejemplo, azul, rojo, verde, naranja, etc.)?

Supongo que querré usar una ColorMatrix de alguna manera, pero no estoy seguro de cómo.

Creo que puedes usar Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY ) . Esto establecería píxeles blancos en rojo, pero no creo que afecte a los píxeles transparentes.

Ver Drawable # setColorFilter

Pruebe este código:

 ImageView lineColorCode = (ImageView)convertView.findViewById(R.id.line_color_code); int color = Color.parseColor("#AE6118"); //The color u want lineColorCode.setColorFilter(color); 

Sé que esta pregunta fue mucho antes de Lollipop, pero me gustaría agregar una buena manera de hacerlo en Android 5. +. Usted hace un dibujable xml que hace referencia al original y establece el tinte sobre el mismo como tal:

 < ?xml version="1.0" encoding="utf-8"?>  

Echa un vistazo a mi blog en esto para más información .

Si tiene un dibujo que es un color sólido y desea cambiarlo a un color sólido diferente, puede usar un ColorMatrixColorFilter . La transparencia se preserva.

 int iColor = Color.parseColor(color); int red = (iColor & 0xFF0000) / 0xFFFF; int green = (iColor & 0xFF00) / 0xFF; int blue = iColor & 0xFF; float[] matrix = { 0, 0, 0, 0, red, 0, 0, 0, 0, green, 0, 0, 0, 0, blue, 0, 0, 0, 1, 0 }; ColorFilter colorFilter = new ColorMatrixColorFilter(matrix); drawable.setColorFilter(colorFilter); 

El nuevo soporte v4 trae tint back to api 4.

puedes hacerlo así

 public static Drawable setTint(Drawable d, int color) { Drawable wrappedDrawable = DrawableCompat.wrap(d); DrawableCompat.setTint(wrappedDrawable, color); return wrappedDrawable; } 

Deberías hacer esto para todas las API:

 Drawable myIcon = getResources().getDrawable( R.drawable.button ); ColorFilter filter = new LightingColorFilter( Color.BLACK, Color.BLACK); myIcon.setColorFilter(filter); 

También uso ImageView para los icons (en ListView o pantalla de configuración). Pero creo que hay una manera mucho más simple de hacer eso.

Use tint para cambiar la superposición de color en su icono seleccionado.

En xml,

android: tint = “@ color / acento”
android: src = “@ drawable / ic_event”

funciona bien ya que viene de AppCompat

Pude hacer esto con el siguiente código, que se toma de una actividad (el diseño es muy simple, solo contiene un ImageView y no se publica aquí).

 private static final int[] FROM_COLOR = new int[]{49, 179, 110}; private static final int THRESHOLD = 3; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_colors); ImageView iv = (ImageView) findViewById(R.id.img); Drawable d = getResources().getDrawable(RES); iv.setImageDrawable(adjust(d)); } private Drawable adjust(Drawable d) { int to = Color.RED; //Need to copy to ensure that the bitmap is mutable. Bitmap src = ((BitmapDrawable) d).getBitmap(); Bitmap bitmap = src.copy(Bitmap.Config.ARGB_8888, true); for(int x = 0;x < bitmap.getWidth();x++) for(int y = 0;y < bitmap.getHeight();y++) if(match(bitmap.getPixel(x, y))) bitmap.setPixel(x, y, to); return new BitmapDrawable(bitmap); } private boolean match(int pixel) { //There may be a better way to match, but I wanted to do a comparison ignoring //transparency, so I couldn't just do a direct integer compare. return Math.abs(Color.red(pixel) - FROM_COLOR[0]) < THRESHOLD && Math.abs(Color.green(pixel) - FROM_COLOR[1]) < THRESHOLD && Math.abs(Color.blue(pixel) - FROM_COLOR[2]) < THRESHOLD; } 

En tu actividad puedes teñir tus recursos de imágenes PNG con un solo color:

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myColorTint(); setContentView(R.layout.activity_main); } private void myColorTint() { int tint = Color.parseColor("#0000FF"); // R.color.blue; PorterDuff.Mode mode = PorterDuff.Mode.SRC_ATOP; // add your drawable resources you wish to tint to the drawables array... int drawables[] = { R.drawable.ic_action_edit, R.drawable.ic_action_refresh }; for (int id : drawables) { Drawable icon = getResources().getDrawable(id); icon.setColorFilter(tint,mode); } } 

Ahora cuando usa el R.drawable. * Debe ser coloreado con el tinte deseado. Si necesita colores adicionales, debe poder .mutar () el dibujable.

Puedes resolverlo usando las bibliotecas compatibles con Android. 🙂

 Drawable drawableWrap = DrawableCompat.wrap(drawable); drawableWrap.mutate(); // to not share its state with any other drawable DrawableCompat.setTint(drawableWrap, ContextCompat.getColor(getContext(), R.color.your_color)); 

Vea este código de ejemplo ” ColorMatrixSample.java ”

 /* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.graphics; import com.example.android.apis.R; import android.app.Activity; import android.content.Context; import android.graphics.*; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; public class ColorMatrixSample extends GraphicsActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new SampleView(this)); } private static class SampleView extends View { private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private ColorMatrix mCM = new ColorMatrix(); private Bitmap mBitmap; private float mSaturation; private float mAngle; public SampleView(Context context) { super(context); mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.balloons); } private static void setTranslate(ColorMatrix cm, float dr, float dg, float db, float da) { cm.set(new float[] { 2, 0, 0, 0, dr, 0, 2, 0, 0, dg, 0, 0, 2, 0, db, 0, 0, 0, 1, da }); } private static void setContrast(ColorMatrix cm, float contrast) { float scale = contrast + 1.f; float translate = (-.5f * scale + .5f) * 255.f; cm.set(new float[] { scale, 0, 0, 0, translate, 0, scale, 0, 0, translate, 0, 0, scale, 0, translate, 0, 0, 0, 1, 0 }); } private static void setContrastTranslateOnly(ColorMatrix cm, float contrast) { float scale = contrast + 1.f; float translate = (-.5f * scale + .5f) * 255.f; cm.set(new float[] { 1, 0, 0, 0, translate, 0, 1, 0, 0, translate, 0, 0, 1, 0, translate, 0, 0, 0, 1, 0 }); } private static void setContrastScaleOnly(ColorMatrix cm, float contrast) { float scale = contrast + 1.f; float translate = (-.5f * scale + .5f) * 255.f; cm.set(new float[] { scale, 0, 0, 0, 0, 0, scale, 0, 0, 0, 0, 0, scale, 0, 0, 0, 0, 0, 1, 0 }); } @Override protected void onDraw(Canvas canvas) { Paint paint = mPaint; float x = 20; float y = 20; canvas.drawColor(Color.WHITE); paint.setColorFilter(null); canvas.drawBitmap(mBitmap, x, y, paint); ColorMatrix cm = new ColorMatrix(); mAngle += 2; if (mAngle > 180) { mAngle = 0; } //convert our animated angle [-180...180] to a contrast value of [-1..1] float contrast = mAngle / 180.f; setContrast(cm, contrast); paint.setColorFilter(new ColorMatrixColorFilter(cm)); canvas.drawBitmap(mBitmap, x + mBitmap.getWidth() + 10, y, paint); setContrastScaleOnly(cm, contrast); paint.setColorFilter(new ColorMatrixColorFilter(cm)); canvas.drawBitmap(mBitmap, x, y + mBitmap.getHeight() + 10, paint); setContrastTranslateOnly(cm, contrast); paint.setColorFilter(new ColorMatrixColorFilter(cm)); canvas.drawBitmap(mBitmap, x, y + 2*(mBitmap.getHeight() + 10), paint); invalidate(); } } } 

La API relevante está disponible aquí :

Hay tantas soluciones, pero nadie sugirió que si el archivo xml de recursos de color ya tiene color, entonces podemos elegir directamente a partir de allí también como se muestra a continuación:

 ImageView imageView = (ImageView) findViewById(R.id.imageview); imageView.setColorFilter(getString(R.color.your_color)); 

Esto funciona con todo con fondo:

Textview, Button …

 TextView text = (TextView) View.findViewById(R.id.MyText); text.setBackgroundResource(Icon); text.getBackground().setColorFilter(getResources().getColor(Color), PorterDuff.Mode.SRC_ATOP); 
 view.getDrawable().mutate().setColorFilter(0xff777777, PorterDuff.Mode.MULTIPLY); 

Gracias a @sabadow

Este fragmento de código funcionó para mí:

 PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(getResources().getColor(R.color.your_color),PorterDuff.Mode.MULTIPLY); imgView.getDrawable().setColorFilter(porterDuffColorFilter); imgView.setBackgroundColor(Color.TRANSPARENT) 

Ejemplo corto para cambiar el color isWorking según el campo isWorking .

Mi forma xml:

 < ?xml version="1.0" encoding="utf-8"?>      

Mi método para cambiar:

 private Drawable getColoredDrawable(int drawableResId, boolean isworking) { Drawable d = getResources().getDrawable(R.drawable.shape); ColorFilter filter = new LightingColorFilter( isworking ? Color.GREEN : Color.RED, isworking ? Color.GREEN : Color.RED); d.setColorFilter(filter); return d; } 

Ejemplo de uso:

 text1.setCompoundDrawablesWithIntrinsicBounds(getColoredDrawable(R.drawable.shape, isworking()), null, null, null); 

Es muy simple cuando usa una biblioteca para hacer eso por usted. Prueba esta biblioteca

Puedes llamar así:

 Icon.on(holderView).color(R.color.your_color).icon(R.mipmap.your_icon).put();