如何在Android中更改Drawable的颜色?

Mat*_*inn 253 android android-drawable

我正在开发一个Android应用程序,我有一个可绘制的,我正在从源图像加载.在这个图像上,我想将所有白色像素转换为不同的颜色,比如说蓝色,然后缓存生成的Drawable对象,以便稍后使用.

例如,假设我有一个20x20的PNG文件,中间有一个白色圆圈,圆圈外的所有内容都是透明的.将白色圆圈变为蓝色并缓存结果的最佳方法是什么?如果我想使用该源图像创建几个新的Drawables(比如蓝色,红色,绿色,橙色等),答案是否会改变?

我猜我想以某种方式使用ColorMatrix,但我不确定如何.

tho*_*nic 213

我想你其实可以使用Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY ).这会将白色像素设置为红色,但我认为它不会影响透明像素.

请参阅Drawable#setColorFilter

  • 如果颜色改变为dinammicaly(例如在适配器中),则drawable必须是可变的.示例:`Drawable.mutate().setColorFilter(0xffff0000,Mode.MULTIPLY)`更多信息:http://www.curious-creature.org/2009/05/02/drawable-mutations/ (66认同)
  • 如果源图标颜色为深色,则乘法不起作用.要使用目标颜色绘制源图标形状,请使用`SRC_IN`:`myImage.getDrawable().mutate().setColorFilter(getResources().getColor(R.color.icon_grey),PorterDuff.Mode.SRC_IN);` (20认同)
  • 当drawable是单色时,这将很好,当它是白色时更好. (9认同)
  • 这正是我所寻找的,尽管令人难以置信的是我们不能用XML做到这一点([除了5.0+以外](https://developer.android.com/training/material/drawables.html#DrawableTint )).在AppCompat中甚至没有Tinting,所以每次我们使用图标而不是使用具有不同颜色色调的选择器时,我们都不得不调用`setColorFilter`.尽管如此,它还是比直接编辑png并拥有额外静态资产更好的解决方案. (2认同)

Nar*_*ren 144

尝试使用此代码:

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


Min*_*Man 91

我知道这个问题在Lollipop之前就已经问过了,但我想在Android 5.上添加一个很好的方法.你创建一个引用原始的xml drawable并在其上设置tint,如下所示:

<?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"/>
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看我的博客文章.

  • Tint通过DrawableCompat支持-v4 (8认同)

小智 62

如果您有一个纯色的drawable,并且想要将其更改为不同的纯色,则可以使用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);
Run Code Online (Sandbox Code Playgroud)

  • 如果你想使用颜色资源而不是字符串(#ff0000等),你可以使用例如int iColor = getResources().getColor(R.color.primary) (3认同)
  • Ben的评论中的代码现已弃用.相反,你可以使用`int iColor = ContextCompat.getColor(context,R.color.primary);`. (3认同)

小智 60

新的支持v4将色彩带回api 4.

你可以这样做

public static Drawable setTint(Drawable d, int color) {
    Drawable wrappedDrawable = DrawableCompat.wrap(d);
    DrawableCompat.setTint(wrappedDrawable, color);
    return wrappedDrawable;
}
Run Code Online (Sandbox Code Playgroud)

  • 从支持库22。 (2认同)
  • 当心!您应该改变新包装的可绘制对象“#mutate()”以避免与状态相关的问题。见 /sf/answers/3121554901/ (2认同)

sud*_*007 48

我也ImageView用于图标(在ListView屏幕或设置屏幕中).但我认为有更简单的方法可以做到这一点.

使用tint来改变你的选择的图标颜色叠加.

在xml中,

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

工作正常,因为它来自 AppCompat

  • 奇迹般有效!简单而完美.这需要标记为已接受的答案. (3认同)
  • 这里有很多好的答案,但是对于OP的问题,这是最好,最简单的解决方案。 (2认同)

hoa*_*u23 41

您应该为所有API执行此操作:

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

  • 当 alpha 用于色调颜色时,这似乎不起作用。 (3认同)
  • 强调我认为前面的评论者所说的,如果 LightingColorFilter 中的 2 个参数不同,此解决方案会更改颜色,例如,`ColorFilter filter = new LightingColorFilter(Color.BLACK, Color.LTGRAY);` 将在可绘制的。 (2认同)

Mat*_*inn 30

我能够使用以下代码执行此操作,该代码取自一个活动(布局非常简单,只包含一个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;
}
Run Code Online (Sandbox Code Playgroud)


Dav*_*las 15

在您的活动中,您可以使用单一颜色为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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在当你使用R.drawable.*时,它应该用所需的色调着色.如果你需要额外的颜色,那么你应该能够.mutate()绘制.


Ric*_*ard 13

您可以使用Android支持compat库解决它.:)

 // 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))
Run Code Online (Sandbox Code Playgroud)


Ham*_*egh 5

view.getDrawable().mutate().setColorFilter(0xff777777, PorterDuff.Mode.MULTIPLY); 
Run Code Online (Sandbox Code Playgroud)

感谢@sabadow


Meh*_*tab 5

此代码片段对我有用:

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

imgView.getDrawable().setColorFilter(porterDuffColorFilter);
imgView.setBackgroundColor(Color.TRANSPARENT)
Run Code Online (Sandbox Code Playgroud)


Mar*_*sad 5

如果您将 drawable 设置为 ImageView,则可以使用 1 个班轮来完成:

yourImageView.setColorFilter(context.getResources().getColor(R.color.YOUR_COLOR_HERE);
Run Code Online (Sandbox Code Playgroud)


Mou*_*ALI 5

为时已晚,但以防万一有人需要它:

   fun setDrawableColor(drawable: Drawable, color: Int) :Drawable {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            drawable.colorFilter = BlendModeColorFilter(color, BlendMode.SRC_ATOP)
            return drawable
        } else {
            drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
            return drawable
        }
    }
Run Code Online (Sandbox Code Playgroud)