1.PorterDuffXferMode
在实现刮刮卡效果之前,我们需要首先了解一下PorterDuffXferMode
上面就是十六种PorterDuff.Mode,但如果你试过就知道,其实并非完全如上面一样。
原因就是,上面的圆形和矩形并不是整个Bitmap,整个方框才是Bitmap。圆形和矩形只是画在里面的,而且那两个Bitmap是完全重叠的,只是里面的图形位置不同。
就像是我画的这个图,整个图形不止圆形还有周围的空白。只有在这种情况下,上面的Demo才是正确的。
但我们一般就是,圆形就是圆形,矩形就是矩形,周围也没有留白。所以在这种情况下,下面的Demo才是正确的
图片来源于:
https://blog.csdn.net/u013085697/article/details/52096703
还有要记得关闭硬件加速,否则有几种模式无法实现。
setLayerType(View.LAYER_TYPE_SOFTWARE, null);//关闭硬件加速
我们来测试一下 PorterDuff.Mode.SRC_IN
原图:
PorterDuff.Mode.SRC_IN:
完全符合!
2.实现刮刮卡效果
思路很简单:
1.重叠绘制两个Bitmap。
2.设置Paint与Path。Paint设置PorterDuff.Mode.SRC_IN。在onTouchEvent()中,Path记录手指滑动的路径,同时,Paint画出透明的路径来显示被覆盖的图片。
首先完成初始化:
private void init(){ mPaint=new Paint(); mPaint.setAlpha(0); mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.ROUND); mPaint.setStrokeCap(Paint.Cap.ROUND); mPaint.setStrokeWidth(50); mPath=new Path(); mBgBitmap= BitmapFactory.decodeResource(getResources(),R.drawable.timg); mFgBitmap=Bitmap.createBitmap(mBgBitmap.getWidth(),mBgBitmap.getHeight(),Bitmap.Config.ARGB_8888); mCanvas=new Canvas(mFgBitmap); mCanvas.drawColor(Color.GRAY); }
然后在onDraw()中绘制Bitmap
canvas.drawBitmap(mBgBitmap,0,0,null); canvas.drawBitmap(mFgBitmap,0,0,null);
最后需要在onTouchEvent中,记录手指移动的路径,并且将路径绘制出来。
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getActionMasked()){ case MotionEvent.ACTION_DOWN: mPath.reset(); mPath.moveTo(event.getX(),event.getY()); break; case MotionEvent.ACTION_MOVE: mPath.lineTo(event.getX(),event.getY()); break; } mCanvas.drawPath(mPath,mPaint); invalidate(); return true; }
这里要明白,整个View其实是有两个Canvas的。
第一个是onDraw的参数,这个画布就是最底层的画布,大小也就是整个View的大小。
第二个是mCanvas,这个是以mFgBitmap为背景的画布,我们的擦除效果也就是在这里实现的。
注意事项:
1.关闭硬件加速。
2.PorterDuffXferMode只对绘制出来的图形才有用,对加载的图片无效。所以不要想着能把底下的图片也擦除掉