web-dev-qa-db-fra.com

Comment changer les couleurs d'un Drawable dans Android?

Je travaille sur une application Android, et j'ai un dessin que je charge depuis une image source. Sur cette image, j'aimerais convertir tous les pixels blancs en une couleur différente, par exemple en bleu, puis mettre en cache l'objet Drawable résultant pour que je puisse l'utiliser plus tard.

Ainsi, par exemple, disons que j'ai un fichier PNG 20x20 avec un cercle blanc au centre et que tout ce qui se trouve en dehors du cercle est transparent. Quel est le meilleur moyen de transformer ce cercle blanc en bleu et de mettre en cache les résultats? La réponse change-t-elle si je souhaite utiliser cette image source pour créer plusieurs nouveaux objets Drawables (par exemple, bleu, rouge, vert, orange, etc.)?

Je suppose que je vais vouloir utiliser un ColorMatrix d'une certaine manière, mais je ne sais pas comment.

249
Matt McMinn

J'ai pu le faire avec le code suivant, tiré d'une activité (la mise en page est très simple, elle contient juste un ImageView et n'est pas publiée ici).

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;
}
30
Matt McMinn

Je pense que vous pouvez en fait simplement utiliser Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY ). Cela définirait les pixels blancs en rouge mais je ne pense pas que cela affecterait les pixels transparents.

Voir Drawable # setColorFilter

210
thom_nic

Essayez ce code:

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

Je sais que cette question a été posée bien avant Lollipop mais je voudrais ajouter un moyen agréable de le faire sur Android 5. +. Vous créez un fichier XML dessinable qui fait référence à celui d'origine et donnez la teinte à celui-ci comme ceci:

<?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"/>
86
MinceMan

Si vous pouvez dessiner une couleur unie et que vous souhaitez le changer en une couleur unie différente, vous pouvez utiliser un ColorMatrixColorFilter. La transparence est préservée.

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);
62
Mike Hill

Le nouveau support v4 ramène la teinte à api 4.

tu peux le faire comme ça

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

J'utilise aussi ImageView pour les icônes (dans ListView ou dans l'écran de paramétrage). Mais je pense qu’il existe un moyen beaucoup plus simple de le faire.

Utilisez tint pour modifier l’incrustation de couleur sur l’icône sélectionnée.

En xml,

Android:tint="@color/accent"
Android:src="@drawable/ic_event" 

fonctionne bien car il vient de AppCompat

48
sud007

Vous devriez le faire pour toutes les API:

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

Dans votre activité, vous pouvez colorer vos ressources d’image PNG avec une seule couleur:

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

Maintenant, lorsque vous utilisez le R.drawable. *, Il doit être coloré avec la teinte souhaitée. Si vous avez besoin de couleurs supplémentaires, vous devriez être capable de .mutate () le dessinable.

14
David Douglas

Vous pouvez le résoudre en utilisant Android support des bibliothèques compatibles.:)

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

Cet extrait de code a fonctionné pour moi:

PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(getResources().getColor(R.color.your_color),PorterDuff.Mode.MULTIPLY);

imgView.getDrawable().setColorFilter(porterDuffColorFilter);
imgView.setBackgroundColor(Color.TRANSPARENT)
3
Mehatab

Découvrez cet exemple de code " 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();
        }
    }
}

L'API correspondante est disponible ici :

3
Adrian

Cela fonctionne avec tout avec le fond:

Textview, Button ...

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

Merci à @sabadow

2
Hamidreza Sadegh

Il y a tellement de solutions que personne ne suggère si le fichier color resource xml a déjà de la couleur, nous pouvons donc choisir directement à partir de là aussi comme ci-dessous:

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

Si vous avez réglé votre dessin sur ImageView, vous pouvez le faire avec une doublure:

yourImageView.setColorFilter(context.getResources().getColor(R.color.YOUR_COLOR_HERE);
1
Martin Nowosad

Petit exemple pour changer la couleur pouvant être dessinée en fonction du champ isWorking.

Ma forme xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:Android="http://schemas.Android.com/apk/res/Android" >
    <solid Android:color="@Android:color/holo_blue_bright" />
    <corners Android:radius="30dp" />
    <size
        Android:height="15dp"
        Android:width="15dp" />
</shape>

Ma méthode pour changer:

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

Exemple d'utilisation:

text1.setCompoundDrawablesWithIntrinsicBounds(getColoredDrawable(R.drawable.shape, isworking()), null, null, null);
1
deadfish
Int color = Color.GRAY; 
// or int color = Color.argb(123,255,0,5);
// or int color = 0xaaff000;

n XMl   /res/values/color.xml
<?xml version="1.0" encoding="utf-8">
<resources>
    <color name="colorRed">#ff0000</color>
</resoures> 

int color = ContextCompat.getColor(context, R.color.colorRed);

GradientDrawable drawableBg = yourView.getBackground().mutate();
drawableBg.setColor(color);
0
Ven Ren