最近学习自定义View然后做了这么个东西,感觉挺有趣。
简单的就不写了就是一个Activity然后在其中使用,就像TextView一样,只需要设置宽高就行了wrap_content和match_parent无所谓了。其他的就是改改包名还有就是图片。
EraserView:
package com.example.administrator.writeapp.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
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;
import com.example.administrator.writeapp.R;
/**
* Created by Administrator on 2019-9-26.
*/
public class EraserView extends View {
Paint paint;
Path path;
Bitmap srcBitmap;
Bitmap desBitmap;
Bitmap disBitmap;
PorterDuffXfermode porterDuffXfermode;
public EraserView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_HARDWARE,null);//关闭硬件加速
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(30);//橡皮擦的宽度
path = new Path();
//S 源图像 D 目标图像 a是alpha透明度,c是color颜色
porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT);//Sa * (1 - Da), Sc * (1 - Da)
srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.one);
desBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.ARGB_8888);
disBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.two);
}
float startX;
float startY;
float endX;
float endY;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();//按下时的x,y坐标
path.moveTo(event.getX(), event.getY());//线段起点位置
return true;
case MotionEvent.ACTION_MOVE:
endX = event.getX();
endY = event.getY();
path.quadTo(startX, startY, endX, endY);//二阶贝济埃曲线,更加光滑
startX = endX;
startY = endY;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
}
invalidate();//确保要在主线程
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(disBitmap, 0, 0, paint);//注释掉这一行可以显示空白效果
//保存指定区域矩形
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
Canvas desCanvas = new Canvas(desBitmap);
desCanvas.drawPath(path, paint);
canvas.drawBitmap(desBitmap, 0, 0, paint);
paint.setXfermode(porterDuffXfermode);
canvas.drawBitmap(srcBitmap, 0, 0, paint);
paint.setXfermode(null);
canvas.restoreToCount(layerId);
}
}
稍作解释,PorterDuff.Mode.SRC_OUT这一个mode是关键,他的描述是Sa * (1 - Da), Sc * (1 - Da),S是源图像,D是目标图像,如果设置了 canvas.drawBitmap(disBitmap, 0, 0, paint),disBitmap就是背景,如果不设置,就是系统默认的背景色,a代表alpha表示透明度,c代表color。根据这个公式,我们通过手指滑动的路径存储在path中,然后将path在onDraw中画出来,这时候da就有了Alpha为1,1-Da就等于零,所以手指划过的地方源图像就消失了,剩下的就是背景色了。刮奖效果就差不多,刮掉上面的遮掩的bitmap,就剩下了背景图片的谢谢惠顾或中奖信息。