先來看下今天能掛到啥樣的妹子吧,完整項目
我們來分析下實現流程吧~
- 其實就是兩個Bitmap,一前一後,前面的是穿着衣服的,後面的是沒穿衣服的, 然後通過一個Path來記錄用戶繪製出來的圖形,然後爲我們的畫筆設置DST_OUT的模式,那麼 與Path重疊部分的DST(目標圖),就是穿着衣服的圖,會變成透明!好噠,很簡單! 我們再慢慢細化!
- 首先我們需要兩個Bitmap,用來存儲前後兩張圖片,這裏我們讓兩個Bitmap都全屏!
- 接着設置下畫筆,圓角,筆寬,抗鋸齒等!
- 再接着定義一個畫Path,即用戶繪製區域的方法,設置Xfermode後畫區域而已!
- 然後重寫onTouchEvent方法,這部分和之前的自定義畫圖板是一樣的!
- 最後重寫onDraw()方法,先繪製背景圖片,調用用戶繪製區域的方法,再繪製前景圖片!
刮刮卡和刮妹子是一樣的邏輯:
刮妹子
public class StripMeiZi extends View{
private Paint mPaint = new Paint();
private Path mPath = new Path();
private Canvas mCanvas;
private Bitmap mBeforeBitmap;
private Bitmap mBackBitmap;
private int mLastX,mLastY;
private int screenW, screenH; //屏幕寬高
private Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);
public StripMeiZi(Context context) {
this(context, null);
}
public StripMeiZi(Context context, AttributeSet attrs) {
super(context, attrs);
screenW = ScreenUtil.getScreenW(context);
screenH = ScreenUtil.getScreenH(context);
init();
}
public StripMeiZi(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void init() {
//背後圖片,這裏讓它全屏
mBackBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.meizi_back1);
mBackBitmap = Bitmap.createScaledBitmap(mBackBitmap, screenW, screenH, false);
//前面的圖片,並繪製到Canvas上
mBeforeBitmap = Bitmap.createBitmap(screenW, screenH, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBeforeBitmap);
mCanvas.drawBitmap(BitmapFactory.decodeResource(getResources(),
R.mipmap.meizi_before1), null, new RectF(0, 0, screenW, screenH), null);
//畫筆相關的設置
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND); // 圓角
mPaint.setStrokeCap(Paint.Cap.ROUND); // 圓角
mPaint.setStrokeWidth(80); // 設置畫筆寬
}
private void drawPath() {
mPaint.setXfermode(mXfermode);
mCanvas.drawPath(mPath, mPaint);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBackBitmap, 0, 0, null);
drawPath();
canvas.drawBitmap(mBeforeBitmap, 0, 0, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
switch (action)
{
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
mPath.moveTo(mLastX, mLastY);
break;
case MotionEvent.ACTION_MOVE:
int dx = Math.abs(x - mLastX);
int dy = Math.abs(y - mLastY);
if (dx > 3 || dy > 3)
mPath.lineTo(x, y);
mLastX = x;
mLastY = y;
break;
}
invalidate();
return true;
}
}
刮獎品
public class GuaGuaCardView_SRCOUT extends View {
private Paint mBitPaint;
private Bitmap BmpDST,BmpSRC,BmpText;
private Path mPath;
private float mPreX,mPreY;
public GuaGuaCardView_SRCOUT(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mBitPaint = new Paint();
mBitPaint.setColor(Color.RED);
mBitPaint.setStyle(Paint.Style.STROKE);
mBitPaint.setStrokeWidth(45);
BmpText = BitmapFactory.decodeResource(getResources(),R.drawable.guaguaka_text1,null);
BmpSRC = BitmapFactory.decodeResource(getResources(),R.drawable.guaguaka,null);
BmpDST = Bitmap.createBitmap(BmpSRC.getWidth(), BmpSRC.getHeight(), Bitmap.Config.ARGB_8888);
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(BmpText,0,0,mBitPaint);
int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
//先把手指軌跡畫到目標Bitmap上
Canvas c = new Canvas(BmpDST);
c.drawPath(mPath,mBitPaint);
//然後把目標圖像畫到畫布上
canvas.drawBitmap(BmpDST,0,0,mBitPaint);
//計算源圖像區域
mBitPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
canvas.drawBitmap(BmpSRC,0,0,mBitPaint);
mBitPaint.setXfermode(null);
canvas.restoreToCount(layerId);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
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:
float endX = (mPreX+event.getX())/2;
float endY = (mPreY+event.getY())/2;
mPath.quadTo(mPreX,mPreY,endX,endY);
mPreX = event.getX();
mPreY =event.getY();
break;
case MotionEvent.ACTION_UP:
break;
}
postInvalidate();
return super.onTouchEvent(event);
}
}