以编程方式更改可绘制颜色


139

我正在尝试通过代码更改白色标记图像上的颜色。我读过下面的代码应该更改颜色,但是我的标记仍然是白色。

Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY )

我错过了什么?还有其他方法可以更改res文件夹中可绘制对象的颜色吗?


接受的答案对我不起作用..使用此“ 如何回答 [1],[1]:stackoverflow.com/questions/5940825/…–
sham.y

我认为这里的所有答案都会更改背景颜色,但不会更改图像的颜色。我说的对吗?谁能告诉我?我在这里尝试了所有解决方案,并且在stackoverflow上也遇到了相同的问题,但是在可能的情况下,它们仅更改背景颜色。所以我认为,我们只能更改背景颜色,而不能更改图像颜色。我是对的吗?
Shirish Herwade

Answers:


258

试试这个:

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

使用DrawableCompat非常重要,因为它提供了向后兼容性以及API 22及更早版本设备上的错误修复。


嗯,颜色仍然是白色。可能与OverlayItems可能导致问题的mapview 类有关吗?它是从我的res文件夹中定期绘制的,没什么特别的……
Johan

那么解决方案是什么?
speedynomads

@ρяσsρєяK您非常棒。非常有帮助
luttu android 2013年

30
如果希望PorterDuff.Mode.SRC_IN与更广泛的源颜色一起使用,则可能更喜欢。
Lorne Laliberte

1
PorterDuffColorFilter构造函数采用ARGB颜色格式
RichX

124

您可以尝试此SVG矢量可绘制

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

4
我见过的最好的方法svg。
apSTRK

1
相对于可接受的答案,更喜欢此选项,尽管两者都可以使用,但是使用此选项,我不必担心要设置可绘制的对象,我只需将它设置在那里,而且它向后兼容,太好了!
RJFares

1
当没有任何效果时,最好的答案就是像魅力!非常感谢!注:这也适用于当你有一个XML绘制在你的ImageView / AppCompatImageView
SJD

1
如何以编程方式将其删除?
Hardik Joshi

1
@HardikJoshi文档说:要清除色彩,请传递nullDrawable#setTintList(ColorStateList)
arekolek,

23

您可能需要在drawable上调用mutate(),否则所有图标都会受到影响。

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

在Lollipop上执行此操作的另一种方法是android 5. +,在可绘制的位图上设置色调,如下所示:

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

如果您想在可绘制对象上使用的颜色数量有限,这将为您工作。查看我的博客文章以获取更多信息


2
真好!顺便说一句,这似乎在棒棒糖之前也很好用。(只需使用minSdkVersion 16Android 4.1.1设备进行测试。)
Jonik 2015年

以这种方式创建位图时,它不会像使用时那样拉伸以适合布局android:background="..."。真奇怪!
2015年

我认为这是因为您不在此处创建九个补丁。
MinceMan 2015年

抱歉,此页面不存在=(
Phan Van Linh

@Jonik您提供的问题中的答案无关紧要。这个问题要求改变Drawable的颜色而不是ImageView的颜色。
Antony.H


10

我写了一个通用函数,您可以在其中传递上下文,图标是id drawable / mipmap图像图标,以及该图标所需的新颜色。

该函数返回一个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

您可以尝试使用ColorMatrixColorFilter,因为您的关键颜色是白色:

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

这对我有用。确保在0x和颜色代码之间放置“ ff”。赞这个0xff2196F3

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

嗨@Bek欢迎来到stackoverflow。如果这对您有用,那么将jsfiddle包含在最小的解决方案中将对此很有帮助。这将帮助发布问题的人正确理解。
Arjun Chaudhary

6

与接受的答案相同,但更简便的方法是:

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

注意,这里的代码是Kotlin。


3

您可能要尝试Mode.LIGHTENMode.DARKEN。Android Javadocs很难解释PorterDuff模式的功能。您可以在这里查看它们:PorterDuff | 安卓

我建议在这里浏览 Mozilla网站上的Compositing (它们没有android具备的所有模式,但是它们有很多)


3

使用这个:对于java

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

对于科特林

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

如果背景有圆角等,则可以使用PorterDuff.Mode.SRC_ATOP。


1

句法

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

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

0

这就是我所做的:

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

像这样创建方法:

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

并像这样使用它:

    changeIconColor(this,R.drawable.ic_home);

0

最简单的方法:

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

要么

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

a,r,g,b:颜色argb值。


仅当OP将使用imageViews而不是drawable时,这才起作用。
SowingFiber

0

对于那些使用Kotlin人来说,一个简单的扩展功能:

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

然后简单地做

background.tint(context, R.color.colorPrimary)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.