Alterar cores desenháveis ​​programaticamente


139

Estou tentando alterar a cor em uma imagem de marcador branco por código. Eu li que o código abaixo deve mudar a cor, mas meu marcador permanece branco.

Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY )

Perdi alguma coisa? Existe alguma outra maneira de alterar as cores nos meus drawables localizados na minha pasta res?


resposta aceita não funcionou para mim .. usado isto Como responder [1], [1]: stackoverflow.com/questions/5940825/…
— sham.y

Eu acho que todas as respostas aqui mudam a cor de fundo, mas não a cor da imagem. Estou certo? Alguém pode me dizer por favor? Eu tentei todas as soluções aqui e também sobre as mesmas perguntas sobre o stackoverflow, mas elas mudam apenas a cor de fundo em alguns casos. Então eu acho que só podemos mudar a cor de fundo, mas não a cor das imagens. Estou certo?
— Shirish Herwade

Respostas:


258

Tente o seguinte:

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

O uso DrawableCompaté importante porque fornece compatibilidade com versões anteriores e correções de bugs nos dispositivos da API 22 e anteriores.


Hmm, a cor permanece branca. Poderia ter a ver com a OverlayItemsclasse hello mapview que pode estar causando o problema? É um drawable regulares da minha pasta res, nada de especial ...
— Johan

Então, qual era a solução?
— speedynomads

@ ρяσѕρєяK você é muito awesome.very útil
— luttu android 15/10/13

30
Você pode preferir PorterDuff.Mode.SRC_IN se desejar que ele funcione com uma variedade maior de cores de origem.
— Lorne Laliberte

1
PorterDuffColorFilter construtor leva formato de cor ARGB
— RichX

124

Você pode tentar isso para svg vector drawable

DrawableCompat.setTint(
    DrawableCompat.wrap(myImageView.getDrawable()),
    ContextCompat.getColor(context, R.color.another_nice_color)
);

4
A melhor maneira que eu já vi para svg.
— apSTRK 18/01

1
prefiro isso à resposta aceita, embora ambas funcionem, mas com essa não preciso me preocupar com o que definir, é só pegar a que já está lá e também é compatível com versões anteriores, ótimo!
— RJFares

1
Melhor resposta quando nada funcionou e não funciona como um encanto! Muito obrigado! Nota: Também funciona para quando você tem um desenho xml no seu imageView / AppCompatImageView
— Sjd 15/17

1
Como removê-lo programaticamente?
— Hardik Joshi

1
A documentação do @HardikJoshi diz: Para limpar a tonalidade, passe nullparaDrawable#setTintList(ColorStateList)
— arekolek

23

Pode ser necessário chamar mutate () na gaveta ou todos os ícones são afetados.

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

21

Outra maneira de fazer isso no Lollipop, o Android 5. +, é definir uma tonalidade em um bitmap desenhável 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"/>

Isso funcionará para você se você tiver um número limitado de cores que deseja usar em suas gavetas. Confira meu post para mais informações .


2
Agradável! Btw, isso parece funcionar bem no pré-pirulito também. (Apenas testei isso com minSdkVersion 16e Android 4.1.1 dispositivo.)
— Jonik

Ao criar um bitmap dessa maneira, ele não se estende para se ajustar ao layout, como faria ao usar android:background="...". Muito estranho!
— Prince

Eu acho que é porque você não está criando um patch nove aqui.
— MinceMan 19/05

Desculpe esta página não existe = (
— Phan Van Linh 29/07

@ Jonik As respostas na sua pergunta são irrelevantes. Esta pergunta está pedindo uma maneira de alterar a cor do Drawable , não o ImageView.
— precisa saber é o seguinte

19

Você pode tentar isso por ImageView. usando setColorFilter().

imageViewIcon.setColorFilter(ContextCompat.getColor(context, R.color.colorWhite));

10

Eu escrevi uma função genérica na qual você pode passar o contexto, o ícone é id drawable / mipmap image icon e a nova cor que você precisa para esse ícone.

Esta função retorna um drawable.

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

9

Você pode tentar um ColorMatrixColorFilter, já que sua cor principal é branca:

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

7

Isso funcionou para mim. Coloque "ff" entre 0x e código de cores. Curtiu isto 0xff2196F3

Drawable mDrawable = ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_vector_home);
                    mDrawable.setColorFilter(new
                            PorterDuffColorFilter(0xff2196F3,PorterDuff.Mode.SRC_IN));

Oi @Bek bem-vindo ao stackoverflow. Se isso funcionasse para você, seria muito útil incluir um jsfiddle com uma solução mínima para mostrar isso. Isso ajudará a pessoa que postou a pergunta a entender corretamente.
— Arjun Chaudhary

6

O mesmo que a resposta aceita, mas um método de conveniência mais simples:

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

Observe que o código aqui é Kotlin.


3

Você pode tentar Mode.LIGHTENou Mode.DARKEN. Os Javadocs do Android são horríveis ao explicar o que os modos PorterDuff fazem. Você pode dar uma olhada neles aqui: PorterDuff | Android

Sugiro dar uma olhada em Compositing no site da Mozilla aqui. (Eles não têm todos os modos que o Android possui, mas eles têm muitos)


3

Use isto: Para java

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

para Kotlin

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

você pode usar o PorterDuff.Mode.SRC_ATOP, se o seu plano de fundo tiver cantos arredondados, etc.


1

Sintaxe

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

Exemplo

myImage.setColorFilter(mContext.getResources().getColor(R.color.deep_blue_new));

0

Isto é o que eu fiz:

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

0

Basta usar

    android:drawableTint="@color/primary_color"

no seu arquivo XML. Substitua primary_color pela cor personalizada


0

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

e use-o assim:

    changeIconColor(this,R.drawable.ic_home);

0

A maneira mais fácil de fazer isso:

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

ou

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

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


Isso funcionará apenas se o OP estiver usando imageViews em vez de drawables.
— SowingFiber

0

Para quem usa o Kotlin, uma simples função de extensão:

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

e então simplesmente

background.tint(context, R.color.colorPrimary)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.