Xfermode有三个子类 :
AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。
PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素异或操作。
PorterDuffXfermode 这是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互。
要应用转换模式,可以使用setXferMode方法,如下所示:
- AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID); borderPen.setXfermode(avoid);
PorterDuff的使用:
参照android apidemo中com.example.android.apis.graphics下的Xfermodes。这里列出已注释的代码:
public class Xfermodes extends GraphicsActivity {
// create a bitmap with a circle, used for the "dst" image 创建一个圆形的bitmap,用来做dst图像
static Bitmap makeDst(int w, int h) {
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(0xFFFFCC44);
c.drawOval(new RectF(0, 0, w*3/4, h*3/4), p);
return bm;
}
// create a bitmap with a rect, used for the "src" image 创建一个矩形bitmap,用来做src图像
static Bitmap makeSrc(int w, int h) {
Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(0xFF66AAFF);
c.drawRect(w / 3, h / 3, w * 19 / 20, h * 19 / 20, p);
return bm;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private static final int W = 64;
private static final int H = 64;
private static final int ROW_MAX = 4; // number of samples per row 每行的数量
private Bitmap mSrcB;
private Bitmap mDstB;
private Shader mBG; // background checker-board pattern 背景棋盘板模型
private static final Xfermode[] sModes = {
new PorterDuffXfermode(PorterDuff.Mode.CLEAR), //所绘制不会提交到画布上。
new PorterDuffXfermode(PorterDuff.Mode.SRC), //显示上层绘制图片
new PorterDuffXfermode(PorterDuff.Mode.DST), //显示下层绘制图片
new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER), //正常绘制显示,上下层绘制叠盖。
new PorterDuffXfermode(PorterDuff.Mode.DST_OVER), //上下层都显示。下层居上显示。
new PorterDuffXfermode(PorterDuff.Mode.SRC_IN), //取两层绘制交集。显示上层。
new PorterDuffXfermode(PorterDuff.Mode.DST_IN), //取两层绘制交集。显示下层。
new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT), //取上层绘制非交集部分。
new PorterDuffXfermode(PorterDuff.Mode.DST_OUT), //取下层绘制非交集部分。
new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP), //取下层非交集部分与上层交集部分
new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP), //取上层非交集部分与下层交集部分
new PorterDuffXfermode(PorterDuff.Mode.XOR), //异或:去除两图层交集部分
new PorterDuffXfermode(PorterDuff.Mode.DARKEN), //取两图层全部区域,交集部分颜色加深
new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN), //取两图层全部,点亮交集部分颜色
new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY), //取两图层交集部分叠加后颜色
new PorterDuffXfermode(PorterDuff.Mode.SCREEN) //取两图层全部区域,交集部分变为透明色
};
private static final String[] sLabels = {
"Clear", "Src", "Dst", "SrcOver",
"DstOver", "SrcIn", "DstIn", "SrcOut",
"DstOut", "SrcATop", "DstATop", "Xor",
"Darken", "Lighten", "Multiply", "Screen"
};
public SampleView(Context context) {
super(context);
mSrcB = makeSrc(W, H);
mDstB = makeDst(W, H);
// make a ckeckerboard pattern 制造一个棋盘模型
Bitmap bm = Bitmap.createBitmap(new int[] { 0xFFFFFFFF, 0xFFCCCCCC,
0xFFCCCCCC, 0xFFFFFFFF }, 2, 2,
Bitmap.Config.RGB_565);
mBG = new BitmapShader(bm,
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
Matrix m = new Matrix();
m.setScale(6, 6);
mBG.setLocalMatrix(m); // 设置变换矩阵
}
@Override protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE); //整个sampleview为白色
Paint labelP = new Paint(Paint.ANTI_ALIAS_FLAG);
//Paint.Align.CENTER 文本被画在x,y origin的横向的中心
//Paint.Align.Left 文本被画在x,y origin的右边
//Paint.Align.Right 文本被画在x,y origin的左边
labelP.setTextAlign(Paint.Align.CENTER);
Paint paint = new Paint();
paint.setFilterBitmap(false);
canvas.translate(15, 35);
int x = 0;
int y = 0;
for (int i = 0; i < sModes.length; i++) {
// draw the border 画边框
paint.setStyle(Paint.Style.STROKE);
paint.setShader(null);
canvas.drawRect(x - 0.5f, y - 0.5f,
x + W + 0.5f, y + H + 0.5f, paint);
// draw the checker-board pattern 画棋盘模型
paint.setStyle(Paint.Style.FILL);
paint.setShader(mBG);
canvas.drawRect(x, y, x + W, y + H, paint);
// draw the src/dst example into our offscreen bitmap
int sc = canvas.saveLayer(x, y, x + W, y + H, null,
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.translate(x, y);
canvas.drawBitmap(mDstB, 0, 0, paint);
paint.setXfermode(sModes[i]);
canvas.drawBitmap(mSrcB, 0, 0, paint); //画前景
paint.setXfermode(null);
canvas.restoreToCount(sc);
// draw the label
canvas.drawText(sLabels[i],
x + W/2, y - labelP.getTextSize()/2, labelP);
x += W + 10;
// wrap around when we've drawn enough for one row
if ((i % ROW_MAX) == ROW_MAX - 1) {
x = 0;
y += H + 30;
}
}
}
}
}
效果图:
参考资料http://blog.youkuaiyun.com/t12x3456/article/details/10432935