首先來看一下效果圖:(這是醫(yī)生的書《Android群英傳》中的一個知識點)
我的 CSDN地址
涉及到的知識點
1. [2D繪圖基礎](http://blog.csdn.net/zone_/article/details/70456348)
2. PorterDuffXfermode
繪制思路:
- 繪制兩個圖層逼泣,第一層繪制想要顯示的圖案扛点,第二層繪制遮罩層(這兩個圖層中渴庆,是第二個圖層覆蓋第一個圖層)
- 讓手指滑過的地方變成透明咸灿,就可以看到第一層的圖片了挣输。
第一步:繪制兩個圖層
先來看一下第一步繪制好之后的效果:
首先是初始化一些數(shù)據(jù):
成員變量:
private Paint mTransparentPaint;//透明的畫筆
private Path mFingerPath;//記錄手指滑過的路徑
private Bitmap mBgBitmap;//第一張圖的 bitmap
private Bitmap mFgBitmap;//第二章圖的 bitmap
private Canvas mCanvas1;//新建的畫布疮薇,用于操作 mFgBitmap
構造方法中初始化的數(shù)據(jù):
mTransparentPaint = new Paint();//設置透明畫筆
mTransparentPaint.setAntiAlias(true);
mTransparentPaint.setAlpha(0);//設置成透明
mTransparentPaint.setStyle(Paint.Style.STROKE);
mTransparentPaint.setStrokeJoin(Paint.Join.ROUND);//讓筆觸和連接處更加圓滑
mTransparentPaint.setStrokeCap(Paint.Cap.ROUND);
mTransparentPaint.setStrokeWidth(50);
mTransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mFingerPath = new Path();//記錄手指滑過的路徑
mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qq2);//第一張圖
mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);//第二章圖
mCanvas1 = new Canvas(mFgBitmap);//mCanvas1 畫布進行的一些列操作都會作用到 mFgBitmap
mCanvas1.drawColor(Color.GRAY);//例如這一步,繪制灰色寡润,會使 mFgBitmap 變成一張全灰色的 bitmap
在 onDraw() 方法中繪制兩個 bitmap :
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBgBitmap, 0,0, null);
canvas.drawBitmap(mFgBitmap, 0,0, null);
}
第二步:讓手指滑過的地方變透明
這里需要重寫 onTouchEvent()捆憎,來記錄手指滑過的路徑 ,那么重寫之后的代碼是這樣的:
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mFingerPath.reset();//因為之前的效果已經(jīng)作用在 fgBitmap 上了,所以需要重置 path 梭纹,避免對下一步造成影響
mFingerPath.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
mFingerPath.lineTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
break;
}
mCanvas1.drawPath(mFingerPath, mTransparentPaint);//使透明的效果作用到 fgBitmap 上躲惰。
invalidate();//執(zhí)行重繪
return true;
}
總結
經(jīng)過上面的兩步繪制,就可以實現(xiàn)刮刮卡的效果了变抽,其實自定義 view 就是坐標的計算和實現(xiàn)思路礁扮。那么完整的代碼是下面這樣的:
public class ScratchCardView extends View {
private Paint mTransparentPaint;//透明的畫筆
private Path mFingerPath;//手指的路徑
private Bitmap mBgBitmap;//第一張圖的 bitmap
private Bitmap mFgBitmap;//第二章圖的 bitmap
private Canvas mCanvas1;//新建的畫布知举,用于操作 mFgBitmap
public ScratchCardView(Context context) {
super(context);
init();
}
public ScratchCardView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ScratchCardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ScratchCardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
mTransparentPaint = new Paint();//設置透明畫筆
mTransparentPaint.setAntiAlias(true);
mTransparentPaint.setAlpha(0);//設置成透明
mTransparentPaint.setStyle(Paint.Style.STROKE);
mTransparentPaint.setStrokeJoin(Paint.Join.ROUND);//讓筆觸和連接處更加圓滑
mTransparentPaint.setStrokeCap(Paint.Cap.ROUND);
mTransparentPaint.setStrokeWidth(50);
mTransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mFingerPath = new Path();//記錄手指滑過的路徑
mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qq2);//第一張圖
mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);//第二章圖
mCanvas1 = new Canvas(mFgBitmap);//mCanvas1 畫布進行的一些列操作都會作用到 mFgBitmap
mCanvas1.drawColor(Color.GRAY);//例如這一步,繪制灰色太伊,會使 mFgBitmap 變成一張全灰色的 bitmap
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mFingerPath.reset();//因為之前的效果已經(jīng)作用在 fgBitmap 上了雇锡,所以需要重置 path ,避免對下一步造成影響
mFingerPath.moveTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
mFingerPath.lineTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
break;
}
mCanvas1.drawPath(mFingerPath, mTransparentPaint);//使透明的效果作用到 fgBitmap 上僚焦。
invalidate();//執(zhí)行重繪
return true;
}
}
好了锰提,我們一步一步實現(xiàn)了最終效果,如果文中有什么知識點是錯誤的或者更好的實現(xiàn)方法芳悲,請及時聯(lián)系我進行修改立肘,以免誤導別人。謝謝名扛。