一、引言
本篇刮刮乐,基于PorterDuffXfermode实现。
Mode.CLEAR
Mode.SRC
Mode.DST
Mode.SRC_OVER
Mode.DST_OVER
Mode.SRC_IN
Mode.DST_IN
Mode.SRC_OUT
Mode.DST_OUT
Mode.SRC_ATOP
Mode.DST_ATOP
Mode.XOR
Mode.DARKEN
Mode.LIGHTEN
Mode.MULTIPLY
Mode.SCREEN
Mode.OVERLAY
Mode.ADD
下面引用网上一张图来显示,google 提供的不同,经与源码对比是因为src 图绘画的位置不同而导致。
效果图:
源码如下:
package com.example.hoperun.defineview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by xuze on 17-8-21.
* 简单刮刮乐的实现
*
*/
public class GuagualeView extends View {
private Paint mPaint = null;
private Bitmap bitmapDst = null;
private Bitmap bitmapSrc = null;
private Bitmap bitmapResult = null;
private Path mPath = null;
private float mPreX,mPreY;
public GuagualeView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(45); //设置画笔
mPath = new Path();
bitmapResult = BitmapFactory.decodeResource(getResources(), R.drawable.first);
bitmapDst = BitmapFactory.decodeResource(getResources(), R.drawable.guaguale);
bitmapSrc = Bitmap.createBitmap(bitmapDst.getWidth(), bitmapDst.getHeight(), Bitmap.Config.ARGB_8888);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//1. 先画结果, 中奖图片
canvas.drawBitmap(bitmapResult, 0, 200, mPaint);
int layId = canvas.saveLayer(0, 0, bitmapDst.getWidth(), bitmapDst.getHeight(), null, Canvas.ALL_SAVE_FLAG);
Canvas mCanvas = new Canvas(bitmapSrc);
mCanvas.drawPath(mPath, mPaint);
//2. 画目标
canvas.drawBitmap(bitmapDst, 0, 0, mPaint);
// //3. 设置
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
canvas.drawBitmap(bitmapSrc, 0, 0, mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(layId);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//绘制指纹path
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(event.getX(), event.getY());
mPreX = event.getX();
mPreY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
// mPath.lineTo(event.getX(), event.getY());
float x = (mPreX + event.getX()) / 2;
float y = (mPreY + event.getY()) / 2;
mPath.quadTo(mPreX, mPreY, x, y);
mPreX = event.getX();
mPreY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
二、CODE解析
1. 构造方法: 创建画笔,路径,3个bitmap(1结果,2目标图,3源图) 结果的图片可以换成字符串等
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(45);
mPath = new Path();
bitmapResult = BitmapFactory.decodeResource(getResources(), R.drawable.first);
bitmapDst = BitmapFactory.decodeResource(getResources(), R.drawable.guaguale);
bitmapSrc = Bitmap.createBitmap(bitmapDst.getWidth(), bitmapDst.getHeight(
2. onDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//1. 先画结果, 中奖图片
canvas.drawBitmap(bitmapResult, 0, 200, mPaint);
int layId = canvas.saveLayer(0, 0, bitmapDst.getWidth(), bitmapDst.getHeight(), null, Canvas.ALL_SAVE_FLAG);
//2. 将path与bitmap结合
Canvas mCanvas = new Canvas(bitmapSrc);
mCanvas.drawPath(mPath, mPaint);
//3. 画目标
canvas.drawBitmap(bitmapDst, 0, 0, mPaint);
//4. 设置样式
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
canvas.drawBitmap(bitmapSrc, 0, 0, mPaint);
mPaint.setXfermode(null);
canvas.restoreToCount(layId);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//绘制指纹path
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mPath.moveTo(event.getX(), event.getY()); //path起点
mPreX = event.getX();
mPreY = event.getY();
return true;
case MotionEvent.ACTION_MOVE:
float x = (mPreX + event.getX()) / 2;
float y = (mPreY + event.getY()) / 2;
mPath.quadTo(mPreX, mPreY, x, y); //绘制贝塞尔曲线
mPreX = event.getX();
mPreY = event.getY();
invalidate();
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return super.onTouchEvent(event);
}