您的位置:首页 > 移动开发 > Android开发

Android 自定义View之PorterDuffXfermode的使用(刮刮卡的效果实现)

2017-04-17 11:33 603 查看
回想一下,在刮奖的时候的那个效果,怎么实现的呢,我们来看一下简单的实现方法。



这里我们要用到画笔特效处理中的PorterDuffXfermode来实现这个效果。在学习PorterDuffXfermode之前,先看看看这张图:



图来自API demo。基本上讲PorterDuffXfermode的文章都引用了该图,类似于取并集,交集的概念。

它控制了两个图像之间的混合现实模式。

注意:PorterDuffXfermode显示的是两个图层交集区域的显示方式DST是先画的图形,src是后画的图形。一般来说,用得最多的是使用一张图片作为另一张图片的遮罩层,进而控制被遮罩层下的图片的显示效果,用得最多的就是DST_IN和SRC_IN,可以实现将矩形图片变成圆形图片或者圆形图片的效果。

不多费口舌,来看看刮刮卡的效果。

第一步,初始化画笔:

mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(100);
mPaint.setStrokeCap(Paint.Cap.ROUND);

mPath = new Path();

mBgBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.home_menu3);
mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mFgBitmap);

mCanvas.drawColor(Color.GRAY);


为了让画笔笔触更润滑一点,设置一下paint的属性, mPaint.setStrokeJoin(Paint.Join.ROUND);和 mPaint.setStrokeCap(Paint.Cap.ROUND);

后面是两个背景了,后背景就是要瓜了之后看到的图,前背景大小根据后背景图大小而定。

接下来就是用户手指滑动产生的路径了,再把路径保存下来,这里使用Path来操作。

@Override
public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
mPath.lineTo(event.getX(), event.getY());
break;
case MotionEvent.ACTION_DOWN:
mPath.reset();
mPath.moveTo(event.getX(), event.getY());
break;
}
mCanvas.drawPath(mPath, mPaint);
invalidate();
return true;
}


最后还有一步,就是使用DET_IN模式将路径绘制到前面覆盖的图层上即可。最关键的一步就是要将画笔的透明度试着为0。这样才能显示擦除的效果。透明度设置为0的原因是因为PorterDuffXfermode进行图层混合时,并不是简单地只是进行图层的计算,同时也会去计算透明通道的值,正式由于混合了有名通道,才形成这样的效果。下面是完整代码:


/**
* Created by dong.he on 2017/3/15 0015.
* <p>
* 画笔特效处理
*/

public class PorterDuffXfermodeView extends View {

private Paint mPaint;
private Canvas mCanvas;
private Path mPath;
private Bitmap mBgBitmap, mFgBitmap;

public PorterDuffXfermodeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

private void init() {
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeWidth(100);
mPaint.setStrokeCap(Paint.Cap.ROUND);//为了让画笔笔触更润滑一点,设置一下paint的属性

mPath = new Path();

mBgBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.home_menu3);
mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mFgBitmap);

mCanvas.drawColor(Color.GRAY);

}
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: mPath.lineTo(event.getX(), event.getY()); break; case MotionEvent.ACTION_DOWN: mPath.reset(); mPath.moveTo(event.getX(), event.getY()); break; } mCanvas.drawPath(mPath, mPaint); invalidate(); return true; }

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBgBitmap, 0, 0, null);
canvas.drawBitmap(mFgBitmap, 0, 0, null);
}


布局:

<com.example.donghe.myview.view.PorterDuffXfermodeView
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_height="200dp" />


自己动手试一下吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息