Как изменить цвета Drawable в Android? - PullRequest
244 голосов
/ 21 августа 2009

Я работаю над приложением для Android, и у меня есть чертеж, который я загружаю из исходного изображения. На этом изображении я хотел бы преобразовать все белые пиксели в другой цвет, скажем синий, и затем кэшировать результирующий объект Drawable, чтобы я мог использовать его позже.

Например, скажем, у меня есть PNG-файл размером 20x20 с белым кружком посередине, и все, что находится за пределами окружности, прозрачно. Какой лучший способ превратить этот белый круг в синий и сохранить результаты в кеше? Изменится ли ответ, если я захочу использовать это исходное изображение для создания нескольких новых объектов Drawable (скажем, синего, красного, зеленого, оранжевого и т. Д.)?

Я предполагаю, что захочу как-нибудь использовать ColorMatrix, но я не знаю, как.

Ответы [ 18 ]

204 голосов
/ 30 апреля 2011

Я думаю, что вы можете просто использовать Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY ). Это установит белые пиксели на красный, но я не думаю, что это повлияет на прозрачные пиксели.

См. Drawable # setColorFilter

141 голосов
/ 30 июня 2012

Попробуйте этот код:

ImageView lineColorCode = (ImageView)convertView.findViewById(R.id.line_color_code);
int color = Color.parseColor("#AE6118"); //The color u want             
lineColorCode.setColorFilter(color);
85 голосов
/ 09 декабря 2014

Я знаю, что этот вопрос задавался задолго до Lollipop, но я хотел бы добавить хороший способ сделать это на Android 5. +. Вы делаете отрисовываемый XML-файл, который ссылается на исходный, и задаете для него оттенок:

<?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"/>
62 голосов
/ 23 июня 2012

Если у вас есть сплошной цвет для рисования, и вы хотите изменить его на сплошной цвет по другому, вы можете использовать ColorMatrixColorFilter. Прозрачность сохраняется.

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);
58 голосов
/ 20 июня 2015

Новая поддержка v4 возвращает оттенок к API 4.

вы можете сделать это так

public static Drawable setTint(Drawable d, int color) {
    Drawable wrappedDrawable = DrawableCompat.wrap(d);
    DrawableCompat.setTint(wrappedDrawable, color);
    return wrappedDrawable;
}
46 голосов
/ 19 сентября 2015

Я также использую ImageView для значков (на ListView или на экране настроек). Но я думаю, что есть гораздо более простой способ сделать это.

Используйте tint, чтобы изменить цвет наложения на выбранный значок.

В xml,

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

работает нормально, поскольку исходит от AppCompat

40 голосов
/ 07 марта 2013

Вы должны сделать это для всех API:

Drawable myIcon = getResources().getDrawable( R.drawable.button ); 
ColorFilter filter = new LightingColorFilter( Color.BLACK, Color.BLACK);
myIcon.setColorFilter(filter);
30 голосов
/ 11 ноября 2009

Я смог сделать это с помощью следующего кода, который взят из упражнения (макет очень простой, просто содержит ImageView и здесь не размещен).

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;
}
14 голосов
/ 21 марта 2014

В своей деятельности вы можете подкрасить ресурсы изображений PNG одним цветом:

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

Теперь, когда вы используете R.drawable. * Он должен быть окрашен с желаемым оттенком. Если вам нужны дополнительные цвета, вы можете использовать .mutate () для рисования.

12 голосов
/ 16 июня 2017

Вы можете решить эту проблему, используя совместимые библиотеки поддержки Android. :)

 // 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...