通常状态图片至少会有两种颜色,按下,普通。一般会切两张图片出来。但是绝对有必要吗?
比如下面的wifi标记
方法一:
Drawable originalDrawable =getResources().getDrawable(R.mipmap.ic_loading_error);
ivA.setImageDrawable(originalDrawable);
ivA.setClickable(true);
ivA.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//点击后变色
Drawable drawable = colorDrawable(v.getResources(),R.mipmap.ic_loading_error,R.color.blue);
ivA.setImageDrawable(drawable);
}
});
public Drawable colorDrawable(Resources res,
@DrawableRes int drawableResId, @ColorRes int colorResId) {
Drawable drawable = res.getDrawable(drawableResId);
int color = res.getColor(colorResId);
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
return drawable;
}
在点击图片后,会变成蓝色
魔术的关键的一行是
drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
如何明确是变哪里的颜色是由 PorterDuff.Mode.SRC_IN来决定的。那它又是啥意思呢?
magic,他居然能够分辨图层,然后根据图层间的关系来决定变色的区域。
那好,如果我想让上面的那张图片变色的是其背景,用SRC_OUT吧。
我在使用过程中发现,该法操作后,会将drawable在内存中的唯一拷贝给修改了,所以当再次读取该drawable都是被改变后的drawable.
方法二:
Drawable originalDrawable = getResources().getDrawable(R.mipmap.ic_loading_error);
ivA.setImageDrawable(originalDrawable);
/**
* 如果不加mutate的话: Android 为了优化系统性能,资源 Drawable 只有一份拷贝,你修改了它,等于所有的都修改了(ivA 和 ivB)。如果你给两个 View 设置同一个资源,
*也是就是他们是共享状态的。
* 幸运的是,Drawable 提供了一个方法 mutate(),来打破这种共享状态,等于就是要告诉系统,我要修改(mutate)这个 Drawable。
*/
Drawable originalDrawable2 = getResources().getDrawable(R.mipmap.ic_loading_error).mutate();
ivB.setImageDrawable(tinyDrawable(originalDrawable2, ColorStateList.valueOf(Color.GREEN)));
public static Drawable tinyDrawable(Drawable drawable, ColorStateList colorStateList) {
Drawable wrapedDrawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTintList(wrapedDrawable, colorStateList);
return wrapedDrawable;
}
总结:
说的很清楚了,同一个图片的drawable在程序里是共用的,方式一很适合来作为一个按钮不同的按下状态展示 ,但如果该画面同时还有另一个按钮也用同一个drawable,那可就不行了,一改全改了。