首先,AvoidXfermode不支持硬件加速,使用它需要关闭硬件加速。其次,最好在新建图层上绘制。
public AvoidXfermode(int opColor, int tolerance, Mode mode)
AvoidXfermode有三个参数,第一个opColor表示一个16进制的可以带透明通道的颜色值例如0x12345678;第二个参数tolerance表示容差值,那么什么是容差呢?你可以理解为一个可以标识“精确”或“模糊”的东西,表示当前颜色和opColor的差异程度;最后一个参数表示AvoidXfermode的具体模式,其可选值只有两个:AvoidXfermode.Mode.AVOID或者AvoidXfermode.Mode.TARGET,两者的意思也非常简单,我们逐一来看。
先说TARGET模式,在该模式下Android会判断画布上的颜色是否会有跟opColor不一样的颜色,opColor可以理解为基准色,仅仅用来做判断。比如我opColor是红色,那么在TARGET模式下就会去判断我们的画布上是否有存在红色(opColor)的地方,如果有,则把该区域“染”上一层我们”画笔的颜色“,否则不“染”色,而tolerance容差值则表示画布上的像素和我们定义的红色之间的差别是多少的时候才去“染”的,比如当前画布有一个像素的色值是(200, 20, 13),而我们的红色值为(255, 0, 0),当tolerance容差值为255时,即便(200, 20, 13)并不等于红色值也会被“染”色,容差值越大“染”色范围越广反之则反。
原始图片
代码
public class MyView extends View {
private Paint mPaint;
private Bitmap mBmp;
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mBmp = BitmapFactory.decodeResource(getResources(),R.drawable.dog);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = 500;
int height = width * mBmp.getHeight()/mBmp.getWidth();
mPaint.setColor(Color.RED);
int layerID = canvas.saveLayer(0,0,width,height,mPaint,Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(mBmp,null,new Rect(0,0,width,height),mPaint);
mPaint.setXfermode(new AvoidXfermode(Color.WHITE,100, AvoidXfermode.Mode.TARGET));
canvas.drawRect(0,0,width,height,mPaint);
canvas.restoreToCount(layerID);
}
}
效果
再看AVOID模式,它与TARGET相反,当容差为0时表示图片颜色与opColor完全不一样时,才会被画笔染色;而当容差为255时表示只要与opColor稍有不同的地方就会被染色。
代码
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = 500;
int height = width * mBmp.getHeight()/mBmp.getWidth();
mPaint.setColor(Color.RED);
int layerID = canvas.saveLayer(0,0,width,height,mPaint,Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(mBmp,null,new Rect(0,0,width,height),mPaint);
mPaint.setXfermode(new AvoidXfermode(Color.WHITE,100, AvoidXfermode.Mode.AVOID));
canvas.drawRect(0,0,width,height,mPaint);
canvas.restoreToCount(layerID);
}
效果如下