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?

Johan
fonte
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.

Coleção K
fonte
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)
);
amorenew
fonte
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);
shicky
fonte
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 .

MinceMan
fonte
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));
Jaydip Meghapara
fonte
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);
Sachin Tanpure
fonte
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);
tiguchi
fonte
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));
Bek
fonte
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.

CorayThan
fonte
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)

sebsebmc
fonte
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.

Ravi.Dudi
fonte
1

Sintaxe

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

Exemplo

myImage.setColorFilter(mContext.getResources().getColor(R.color.deep_blue_new));
Om Prakash Sharma
fonte
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;
}
Edwin
fonte
0

Basta usar

    android:drawableTint="@color/primary_color"

no seu arquivo XML. Substitua primary_color pela cor personalizada

Arvina Kori
fonte
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);
sana ebadi
fonte
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.

Anubhav
fonte
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)
Chapz
fonte