public class XfermodesView extends View {
private Context context;
/**每个item的大小*/
private int itemLength;
/**每行的数量*/
private static final int ROW_MAX = 4;
/**首先绘制的黄色的Bitmap*/
private Bitmap mDstBitmap;
/**然后绘制的蓝色的Bitmap*/
private Bitmap mSrcBitmap;
/**灰白相间的背景图渲染器*/
private Shader bitmapShader;
private Paint textPaint;
private Paint bitmapPaint;
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 XfermodesView(Context context) {
super(context);
this.context = context;
itemLength = dp2px(70);
mSrcBitmap = makeSrcBitmap(itemLength, itemLength);
mDstBitmap = makeDstBitmap(itemLength, itemLength);
//根据width和height创建空位图,然后用指定的颜色数组colors来从左到右从上至下依次填充颜色
Bitmap bitmap = Bitmap.createBitmap(new int[] { 0xFFFFFFFF, 0xFFCCCCCC, 0xFFCCCCCC, 0xFFFFFFFF }, 2, 2, Bitmap.Config.RGB_565);
bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
Matrix matrix = new Matrix();
matrix.setScale(dp2px(2), dp2px(2));//本来背景是一个白像素一个会像素,太密集了,此操作目的是放大背景
bitmapShader.setLocalMatrix(matrix);
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(dp2px(10));
bitmapPaint = new Paint();
bitmapPaint.setFilterBitmap(false);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.translate(dp2px(5), dp2px(20));
int x = 0;
int y = 0;
for (int i = 0; i < sModes.length; i++) {
// 画正方形边框
bitmapPaint.setStyle(Paint.Style.STROKE);
bitmapPaint.setShader(null);//不去渲染
canvas.drawRect(x - 0.5f, y - 0.5f, x + itemLength + 0.5f, y + itemLength + 0.5f, bitmapPaint);//+-0.5f只是为了精确
//画灰白相间的背景
bitmapPaint.setStyle(Paint.Style.FILL);
bitmapPaint.setShader(bitmapShader);//用上面指定的渲染器渲染
canvas.drawRect(x, y, x + itemLength, y + itemLength, bitmapPaint);
// 根据不同的模式画两个图
int sc = canvas.saveLayer(x, y, x + itemLength, y + itemLength, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG //1|2|4|8|16
| Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.translate(x, y);
// 以下是最核心的三行代码
canvas.drawBitmap(mDstBitmap, 0, 0, bitmapPaint);
bitmapPaint.setXfermode(sModes[i]);
canvas.drawBitmap(mSrcBitmap, 0, 0, bitmapPaint);
bitmapPaint.setXfermode(null);
canvas.restoreToCount(sc);
// 画标题
canvas.drawText(sLabels[i], x + itemLength / 2, y - textPaint.getTextSize() / 2, textPaint);
x += itemLength + dp2px(5);
//画完一行后移到下一行
if ((i % ROW_MAX) == ROW_MAX - 1) {
x = 0;
y += itemLength + dp2px(20);
}
}
}
private Bitmap makeDstBitmap(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;
}
private Bitmap makeSrcBitmap(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;
}
private int dp2px(float dpValue) {
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}