先来张效果图哈, 我们可以在上面随意的擦擦擦~~~~
先跟大家讲一下实现的原理哈, 这里我们主要用到了 paint.setXfermode(PorterDuffXfermode portermode) ,设置画笔的混合模式,这里模式有十多种, 我就不贴图了. 大家可以自行百度~~
思路 :我们需要自己的new Canvas(bitmap) 来注入前景bitmap, 在onDraw方法里面 利用canvas 画出前景bitmap和背景bitmap. 然后利用自己mCanvas.drawPath(mPath,mPaint) 来改变效果.
这里我们使用了 PorterDuff.Mode.DST_IN 模式, 代表为上层下层重合处 显示下层.
利用的就是这么多了. 大家看代码吧. 一扫就会咯~
public class Eraser extends View {
private PorterDuffXfermode portermode;
private Canvas mCanvas;
private Bitmap forgBitmap;
private Bitmap backgBitmap;
private Path mPath;
private Paint mPaint;
private int sW;
private int sH;
private Activity mContext;
private DisplayMetrics outMetrics;
private float preX; // 上一个X
private float preY; // 上一个Y
private static final int MOVE_DISTANCE = 5;
public Eraser(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = (Activity) context;
calc();
initView(context);
}
/**
* 计算屏幕高度
*/
private void calc() {
outMetrics = new DisplayMetrics();
mContext.getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
sW = outMetrics.widthPixels;
sH = outMetrics.heightPixels;
}
private void initView(Context context) {
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); // 抗锯齿,抗抖动
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setARGB(128, 255, 0, 0);
mPaint.setStrokeWidth(50);
mPaint.setStyle(Paint.Style.STROKE);// 描边
mPaint.setStrokeJoin(Join.ROUND);// 设置路径结合处样式
mPaint.setStrokeCap(Paint.Cap.ROUND); // 设置笔触类型
forgBitmap = Bitmap.createBitmap(sW, sH, Config.ARGB_8888);
mCanvas = new Canvas(forgBitmap);
mCanvas.drawColor(0xFF808080);
backgBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.tupian);// 背景图
backgBitmap = Bitmap.createScaledBitmap(backgBitmap, sW, sH, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(backgBitmap, 0, 0, null); // 画背景
canvas.drawBitmap(forgBitmap, 0, 0, null); // 画前景
mCanvas.drawPath(mPath, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.reset();
mPath.moveTo(x, y); //起始点
preX = x;
preY = y;
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(x - preX);
float dy = Math.abs(y - preY);
if (dx > MOVE_DISTANCE || dy > MOVE_DISTANCE) {
//赛贝尔曲线
mPath.quadTo(preX, preY, (x + preX) / 2, (y + preY) / 2);
// mPath.quadTo(preX, preY, x, y);
preX = x;
preY = y;
}
break;
}
invalidate();
return true;
}
}