可绘制对象 => 灰度化

30

如何将彩色Drawable转换为灰度Drawable(以指示禁用状态)?

编辑:
B / W => 灰度

4个回答

108

我知道这个问题早就有人问过了,但是我找到了一个更简单的解决方案。如果你有一个Drawable并且只想在灰度下显示同样的drawable,那么不需要画布或者绘制器...

protected Drawable convertToGrayscale(Drawable drawable)
{
    ColorMatrix matrix = new ColorMatrix();
    matrix.setSaturation(0);
    
    ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
    
    drawable.setColorFilter(filter);
    
    return drawable;
}

1
好的提示! 有趣的是,如果您通过传递ContextCompat.getDrawable(context, R.drawable.myId)来运行此方法;下次需要获取相同的drawable时,颜色过滤器已经设置好了。就我而言,我需要删除颜色过滤器才能使我的drawable恢复颜色 :) - Tobliug
6
在应用颜色过滤器之前,只需对可绘制对象使用mutate()方法即可。 可绘制对象的属性在实例之间是共享的,因此通过进行突变,您可以创建另一个该可绘制对象的“副本”。 在突变之后使用颜色过滤器是安全的,不会影响您的其他可绘制对象实例。 - user2154462

19

显然你可以使用ColorMatrix类来进行任何形式的颜色空间转换。它有一个setSaturation()方法,可以轻松地为你创建彩色到灰度的转换(将饱和度置为零)。

因此,你可以使用该滤镜对图像进行重新绘制。我没有尝试过这个方法,但它应该有效:

Bitmap grayscaleBitmap = Bitmap.createBitmap(
    colorBitmap.getWidth(), colorBitmap.getHeight(),
    Bitmap.Config.RGB_565);

Canvas c = new Canvas(grayscaleBitmap);
Paint p = new Paint();
ColorMatrix cm = new ColorMatrix();

cm.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(cm);
p.setColorFilter(filter); 
c.drawBitmap(colorBitmap, 0, 0, p);

3

针对 @intgr 的回答,我有一些评论。
1. 使用Bitmap.Config.ARGB_8888来保留 alpha 通道。
2. 可以加入一些额外的代码:

//remember, you are converting a .png image, as opposed to a Drawable defined in .xml  
Bitmap colorBitmap = ((BitmapDrawable)drawable).getBitmap();    
// the code by intgr  
Drawable grayscaleDrawable = new BitmapDrawable(grayscaleBitmap);

1
小错误:Bitmap.Config.RGB_8888 应该是 Bitmap.Config.ARGB_8888。然后就可以正常工作了,谢谢。 - Minsky

1

你是否特别想要程序化地实现,而不仅仅是使用被禁用的图像版本? 你可以引用一个XML drawable,类似于:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_window_focused="false" android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_window_focused="false" android:state_enabled="false"
        android:drawable="@drawable/btn_default_normal_disable" />
    <item android:state_pressed="true" 
        android:drawable="@drawable/btn_default_pressed" />
    <item android:state_focused="true" android:state_enabled="true"
        android:drawable="@drawable/btn_default_selected" />
    <item android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_focused="true"
        android:drawable="@drawable/btn_default_normal_disable_focused" />
    <item
         android:drawable="@drawable/btn_default_normal_disable" />
</selector>

是的,我想在每个实例的基础上进行。不过感谢你提供的代码片段。 - yanchenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接