Android 5.0 以上 ImageView 有支持着色的api:
imageView.setImageTintList(ColorStateList.valueOf(Color.RED));
缺点:
1、只有5.0及以上的设备才支持
2、只能着纯色,不能着渐变色
public static Bitmap addGradient(Bitmap originalBitmap, int[] colors) {//给originalBitmap着渐变色
if (colors == null || colors.length == 0) {//默认色处理
colors = new int[]{Color.parseColor("#ff9900"), Color.parseColor("#ff9900")};
} else if (colors.length == 1) {//单色处理
int[] newColor = new int[]{colors[0], colors[0]};
colors = newColor;
}
int width = originalBitmap.getWidth();
int height = originalBitmap.getHeight();
Canvas canvas = new Canvas(originalBitmap);//Canvas中Bitmap是用来保存像素,相当于画纸
Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, 0, width, height, colors, null, Shader.TileMode.CLAMP);//shader:着色器,线性着色器设置渐变从左上坐标到右下坐标
paint.setShader(shader);//设置着色器
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//设置图像混合模式
canvas.drawRect(0, 0, width, height, paint);
return originalBitmap;
}
public static Bitmap getGradientBitmap(Context context, int drawableId, int[] colors) {
//android不允许直接修改res里面的图片,所以要用copy方法
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableId)
.copy(Bitmap.Config.ARGB_8888, true);
addGradient(bitmap, colors);
return bitmap;
}
imageView.setImageTintList(ColorStateList.valueOf(Color.RED));
imageView2.setImageBitmap(getGradientBitmap(this,R.drawable.hi,new int[]{Color.GREEN,Color.BLUE}));
效果:(第一个为原图)
附录:
Shader类源码简析:
Shader类中定义了一个 枚举: enum TileMode{CLAMP, REPEAT, MIRROR}; 定义了三种渲染图形的模式。
注: 如果图片和目标区域一样大,设置任意模式的效果是一样的。
1. CLAMP: 如果图片小于目标区域,则用该图片的边缘颜色继续填充剩余空间。
2. REPEAT(重复): 如果图片小于目标区域,则复制该图片继续填充剩余空间。
3. MIRROR(镜像): 如果图片小于目标区域,则从图片边缘按和图片上原本颜色相反的颜色来填充剩余空间。
Shader子类解释:Shader的子类全部都没有自己定义的方法,纯粹靠各自的 构造方法 实现效果,所以下面的描述基本只注重于构造方法。所有的Shader子类的使用方法都一样: 给自己的Paint设置这个属性(mPaint.setShader(XXXX)),传入自己建立的Shader,然后使用Canvas画出来即可。 注:为了观察清晰起见,我画出的图片和目标区域是一样大的,也就不存在渲染模式的问题了,故渲染模式都采用CLAMP。
BitmapShader(位图渲染器);
构造方法: public BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY);
参数解释: 第一个参数Bitmap: 想要渲染出来的 位图。 设置什么图片,用canvas就会画出什么图片。
第二个参数,第三个参数分别是:水平方向上的渲染模式, 垂直方向上的渲染模式。LinearGradient(线性渐变渲染器);
构造方法1: public LinearGradient(float startX, float startY, float endX, float endY, int color0, int color1, Shader.TileMode tile);
参数解释: 前四个参数: 分别是 起点、终点的坐标。
第五个参数(color0)、第六个参数(color1): 从color0渐变到color1.
第七个参数:渲染模式。
构造方法2: public LinearGradient(float startX, float startY, float endX, float endY, int[] colors, float[] positions, Shader.TileMode tile);
参数解释: 前四个参数: 分别是 起点、终点的坐标。
第五个参数: 颜色数组,在这个数组中的颜色值会 按照先后顺序显示在目标区域的特定位置。
第六个参数: 颜色位置数组, 这个数组的长度必须和颜色数组的长度一致,这个数组的值的大小必须是从0到1(将目标区域整体看做1), 每一个值对应颜色数组中的颜色,决定了该颜色显示的位置。分配完这些颜色之后,剩下的空白部分由相邻颜色的渐变颜色填充。该参数如果设置为null,则所有颜色数组中的颜色平均占用目标区域。
第七个参数: 渲染模式。RadialGradient(圆形渐变渲染器);
构造方法1: public RadialGradient(float centerX, float centerY, float radius, int color0, int color1, Shader.TileMode tile);
参数解释: 前三个参数: 渲染圆心坐标, 半径。
后三个参数: 参考LinearGradient。
构造方法2: public RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] positions, Shader.TileMode tile);
参数解释: 前三个参数: 渲染圆心坐标, 半径。
后三个参数: 参考LinearGradient。SweepGradient(扫掠渐变渲染器);
构造方法1: public SweepGradient(float centerX, float centerY, int color0, int color1);
参数解释:与之前不同的是,这个构造方法没有 渲染模式 这个参数, 也就是说,不管目标区域有多大,都可以全部渲染。
前两个参数: 渲染中心坐标。(中心随你设置,不一定是图形的中心)
后两个参数: 参考 LinearGradient。
构造方法2: public SweepGradient(float centerX, float centerY, int[] colors, float[] positions);
参数解释: 前两个参数: 渲染中心坐标。(中心随你设置,不一定是图形的中心)
后两个参数: 参考 LinearGradient。ComposeShader(组合渲染器);
组合渲染器可以将两个shader的结果混合在一起,混合的方式是使用 PorterDuff 两人的混合模式。
构造方法1: public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode);
参数解释: 前两个参数: 要混合的 shader
最后一个参数: PorterDuff混合模式。
构造方法2: public ComposeShader(Shader shaderA, Shader shaderB, XferMode mode);
参数解释:前两个参数: 要混合的 shader
最后一个参数: Xfermode 参数--- Xfermode 下属三个子类:AvoidXfermode, PixelXorXfermode, PorterDuffXfermode,可以看到前两个已过期,故,这个构造方法 基本可以无视了。
附录原文链接:https://blog.csdn.net/ShortChin/article/details/51655082