ProterDuffXfermode
图片混合模式(18种)
先画的为目标图(DST)
后画的为源图(SRC)
画图与Bitmap的区别
官方示例采用的drawBitmap,是两个大小相同且绘制区域并不会充满整个bitmap
画图例如drawCircle等,使用setXfermode其作用域是第二次绘制的图案的部分,所以部分的DST(目标图)本应该改变但没有
官方API示例源码
MainActivity.java
public class MainActivity extends AppCompatActivity{
static Bitmap makeDst(int w,int h){
Bitmap bm = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(0xFFFFCC44);
canvas.drawOval(new RecF(0,0,w*3/4,h*3/4),p);
return bm;
}
static Bitmap makeSrc(int w,int h){
Bitmap bm = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bm);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(0xFF66AAFF);
canvas.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));
}
}
SampleView.java
private static class SampleView extends View{
private static final int W = 200;
private static final int H = 200;
private static final int ROW_MAX = 4;
private Bitmap mSrcB;
private Bitmap mDstB;
private Shader mBG;
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","Mutiply","Screen"
};
private 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);
Paint labelP = new Paint(Paint.ANTI_ALIAS_FLAG);
labelP.setTextAlign(Paint.Align.CENTER);
Paint paint = new Paint();
paint.setFilterBitmao(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 cheker-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.ALL_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;
}
}
}
}
效果图
原始的画图模式
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawARGB(255,255,156,161);//设置背景色
drawDst(canvas,mPaint);
drawSrc(canvas,mPaint);
}
private void drawDst(Canvas canvas,Paint p){
p.setColor(0xFFFFCC44);
int w = canvas.getWidth()/3;
canvas.drawCircle(w,w,w,p);
}
private void drawSrc(Canvas canvas,Paint paint){
paint.setColor(0xFF66AAFF);
int r = canvas.getWidth()/3;
canvas.drawRect(r,r,r*2.7f,r*2.7f,paint);
}
CLEAR
源覆盖的目标图清零
画图
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawARGB(255,255,156,161);
drawDst(canvas,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
drawSrc(canvas,mPaint);
mPaint.setXfermode(null);
}
实现了效果,但是是黑色一块
根据源码实现不加图层渲染的CLEAR模式
使用两个Bitmap进行操作,但是不加canvas.saveLayer()
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mDstBitmap,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawBitmap(mSrcBitmap,0,0,mPaint);
mPaint.setXfermode(null);
}
原因:
Activity本身的颜色是黑色,所以CLEAR模式下,两个Bitmap实现了CLEAR效果,所以展示的是Activity的颜色(貌似其余人的都是白色的?
加了图层渲染后
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(mDstBitmap,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawBitmap(mSrcBitmap,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
}
实现了效果
按照传统的画图形式呈现CLEAR
先画圆(Dst),画笔设置PorterDuff.Mode.CLEAR后,再绘制矩形(此处加了canvas.saveLayer())
实际上作用域为第二次绘画的大小
SRC
定义/概念
源像素(SRC)替换目标像素(DST)
传统的画图形式
不加图层渲染
int w = 200;
int h = 200;
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
加图层渲染
int w = 200;
int h = 200;
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
使用drawBitmap形式
实现官方效果
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
DST
概念
源像素被丢弃,目标像素保留
这种情况下,不论是传统形式还是官方示例操作,或者是加不加图层渲染,呈现的结果都一样
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
//canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST));
mPaint.setColor(Color.GREEN);
//canvas.drawBitmap(mSrcB,0,0,mPaint);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
SRC_OVER
概念
源像素绘制在目标像素之上
结论同上
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
//canvas.drawCircle(w/3,h/3,h/3,mPaint);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
//canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
DST_OVER
概念
源像素绘制在目标像素后面
画图形式
不加图层渲染
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
图层渲染
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
drawBitmap
效果对应同上
SRC_IN
概念
保留覆盖目标像素的源像素,丢弃剩余的源像素和目标像素
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
画图形式
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
DST_IN
概念
保留覆盖源像素的目标像素,丢弃剩余的源像素和目标像素
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
画图形式
作用域是第二次绘制的,第二次绘制的是源像素,所以会显示不见,只有目标像素
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
SRC_OUT
概念
保留不覆盖目标像素的源像素,丢弃覆盖目标像素的源像素,丢弃所有目标像素
画图
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
DST_OUT
概念
保留未被源像素覆盖的目标像素,丢弃被源像素覆盖的目标像素,丢弃所有的源像素
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
画图
同上
SRC_ATOP
概念
丢弃不覆盖目标像素的源像素,在目标像素上绘制剩余的源像素
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
画图
结果同上
DST_ATOP
概念
丢弃未被源像素覆盖的目标像素,在源像素上绘制剩余的目标像素
画图
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
mPaint.setColor(Color.GREEN);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
XOR
概念
丢弃源像素覆盖目标像素的源像素和目标像素,,绘制剩余的源像素
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
画图
同上
DARKEN
概念
保留源像素和目标像素的最小分量
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
画图
同上
LIGHTEN
概念
保留源像素和目标像素最大的分量
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(Color.RED);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN));
mPaint.setColor(Color.GREEN);
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
画图
同上
MULTIPLY
概念
源像素和目标像素相乘
画图
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
mPaint.setColor(0xFFFFCC44);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
mPaint.setColor(0xFF66AAFF);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
drawBitmap
int sc = canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),null,Canvas.ALL_SAVE_FLAG);
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(mSrcB,0,0,mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(sc);
SCREEN
概念
先绘制源像素和目标像素,再减去源像素乘以目标
drawBitmap
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN));
canvas.drawBitmap(mSrcB,0,0,mPaint);
画图
同上
ADD
概念
将源像素添加到目标像素并使结果饱和
drawBitmap
canvas.drawBitmap(mDstB,0,0,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
canvas.drawBitmap(mSrcB,0,0,mPaint);
画图
同上
OVERLAY
概念
Multiplies or screens the source and destination depending on the destination color.
画图
mPaint.setColor(0xFFFFCC44);
canvas.drawCircle(w/3,h/3,h/3,mPaint);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.OVERLAY));
mPaint.setColor(0xFF66AAFF);
canvas.drawRect(w/3,h/3,w/4*3,h/4*3,mPaint);
drawBitmap
同上
整体
MyView.java
private void init(){
mPaint = new Paint();
mPaint.setColor(Color.RED);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int sc = canvas.saveLayer(0,0,getWidth(),getHeight(),mPaint);
XfermodeUtil.drawPattern(canvas,mPaint);
canvas.restoreToCount(sc);
}
XfermodeUtil.java
public static final Xfermode[] sModes = {
new PorterDuffXfermode(PorterDuff.Mode.ADD),
new PorterDuffXfermode(PorterDuff.Mode.CLEAR),
new PorterDuffXfermode(PorterDuff.Mode.DST),
new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP),
new PorterDuffXfermode(PorterDuff.Mode.DST_IN),
new PorterDuffXfermode(PorterDuff.Mode.DST_OUT),
new PorterDuffXfermode(PorterDuff.Mode.DARKEN),
new PorterDuffXfermode(PorterDuff.Mode.DST_OVER),
new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY),
new PorterDuffXfermode(PorterDuff.Mode.OVERLAY),
new PorterDuffXfermode(PorterDuff.Mode.SCREEN),
new PorterDuffXfermode(PorterDuff.Mode.SRC),
new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP),
new PorterDuffXfermode(PorterDuff.Mode.SRC_IN),
new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER),
new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT),
new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN),
new PorterDuffXfermode(PorterDuff.Mode.XOR)
};
public static void drawPattern(Canvas canvas, Paint mPaint){
canvas.drawCircle(100,100,100,mPaint);
canvas.drawCircle(400,100,100,mPaint);
canvas.drawCircle(800,100,100,mPaint);
canvas.drawCircle(100,400,100,mPaint);
canvas.drawCircle(400,400,100,mPaint);
canvas.drawCircle(800,400,100,mPaint);
canvas.drawCircle(100,700,100,mPaint);
canvas.drawCircle(400,700,100,mPaint);
canvas.drawCircle(800,700,100,mPaint);
canvas.drawCircle(100,1000,100,mPaint);
canvas.drawCircle(400,1000,100,mPaint);
canvas.drawCircle(800,1000,100,mPaint);
canvas.drawCircle(100,1300,100,mPaint);
canvas.drawCircle(400,1300,100,mPaint);
canvas.drawCircle(800,1300,100,mPaint);
canvas.drawCircle(100,1600,100,mPaint);
canvas.drawCircle(400, 1600,100,mPaint);
canvas.drawCircle(800,1600,100,mPaint);
mPaint.setColor(Color.GREEN);
mPaint.setXfermode(sModes[0]);
canvas.drawRect(100,100,300,300,mPaint);
mPaint.setXfermode(sModes[1]);
canvas.drawRect(400,100,600,300,mPaint);
mPaint.setXfermode(sModes[2]);
canvas.drawRect(800,100,900,300,mPaint);
mPaint.setXfermode(sModes[3]);
canvas.drawRect(100,400,300,600,mPaint);
mPaint.setXfermode(sModes[4]);
canvas.drawRect(400,400,600,600,mPaint);
mPaint.setXfermode(sModes[5]);
canvas.drawRect(800,400,1000,600,mPaint);
mPaint.setXfermode(sModes[6]);
canvas.drawRect(100,700,300,900,mPaint);
mPaint.setXfermode(sModes[7]);
canvas.drawRect(400,700,600,900,mPaint);
mPaint.setXfermode(sModes[8]);
canvas.drawRect(800,700,1000,900,mPaint);
mPaint.setXfermode(sModes[9]);
canvas.drawRect(100,1000,300,1200,mPaint);
mPaint.setXfermode(sModes[10]);
canvas.drawRect(400,1000,600,1200,mPaint);
mPaint.setXfermode(sModes[11]);
canvas.drawRect(800,1000,1000,1200,mPaint);
mPaint.setXfermode(sModes[12]);
canvas.drawRect(100,1300,300,1500,mPaint);
mPaint.setXfermode(sModes[13]);
canvas.drawRect(400,1300,600,1500,mPaint);
mPaint.setXfermode(sModes[14]);
canvas.drawRect(800,1300,1000,1500,mPaint);
mPaint.setXfermode(sModes[15]);
canvas.drawRect(100,1600,300,1800,mPaint);
mPaint.setXfermode(sModes[16]);
canvas.drawRect(400,1600,600,1800,mPaint);
mPaint.setXfermode(sModes[17]);
canvas.drawRect(800,1600,1000,1800,mPaint);
}
输出
注
BitmapShader
使用特定的图片来作为纹理来使用
构造函数
//bitmap:作为纹理的图片
//tileX/Y:在X/Y方向纹理的绘制模式
public BitmapShader(@NonNull Bitmap bitmap,TileMode tileX,TileMode tileY)