自定义view之PorterDuffXfermode实现刮刮卡

首先 先来看看刮刮卡的实现demo吧
自定义view之PorterDuffXfermode实现刮刮卡_第1张图片
效果棒棒哒!

在看代码之前,我们先来了解下PorterDuffXfermode。

PorterDuffXfermode
PorterDuffXfermode设置的是两个图层交集区域的显示方式,dst是先画的图形,而src是后画的图形。
当然,这些模式也不是经常使用的,用的最多的是,使用一张图片作为另一张图片的遮罩层,通过控制遮罩层的图形,来控制下面被遮罩图形的显示效果。其中最常用的就是通过DST_IN、SRC_IN模式来实现。
自定义view之PorterDuffXfermode实现刮刮卡_第2张图片

我们的刮刮卡也是通过这个原理实现的。在初始状态下,上面的图层会将下面整个图层覆盖,当你用手刮上面的图层的时候,下面的图层会慢慢显示出来,这也类似很多画图工具中的橡皮擦效果。
下面具体来分析实现原理。

首先需要做一些初始化工作,例如背景图、遮罩图和我们画图的Paint的一些属性,代码如下:

        mPaint = new Paint();
        mPaint.setAlpha(0);
        //设置混合模式为DST_IN
        mPaint.setXfermode(
                new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        //设置画笔,让笔触和连接处更加圆滑
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeWidth(50);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPath = new Path();
        //设置背景图
        mBgBitmap = BitmapFactory.decodeResource(getResources(),
                R.mipmap.beauty);
        //设置遮罩图
        mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(),
                mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mFgBitmap);
        mCanvas.drawColor(Color.GRAY);

在上面的代码中,给Paint设置一些属性,让他的笔触和连接处更加圆滑一点,即Paint.Join.ROUND和Paint.Cap.ROUND属性。
将Paint的透明度设为0,这样才能显示出橡皮擦的效果,这是因为在使用PorterDuffXfermode进行图层混合时,并不是简单的只进行图层的计算,同事也会去计算透明通道的值。

接下来,看一下如何获取用户手指滑动所产生的路径。

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            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;
    }

好了,到这里代码估计就清晰了。首先初始化了一张背景图和一张灰色的图,并且混合模式为DST_IN,在滑动的时候,上层的灰色变透明,下层的和上层的合并,就出现了类似的效果。

最后看一下全部代码:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.example.cntvuser.myapplication.R;

public class XfermodeView extends View {

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

    public XfermodeView(Context context) {
        super(context);
        init();
    }

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

    public XfermodeView(Context context, AttributeSet attrs,
                        int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAlpha(0);
        //设置混合模式为DST_IN
        mPaint.setXfermode(
                new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        //设置画笔,让笔触和连接处更加圆滑
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeWidth(50);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPath = new Path();
        //设置背景图
        mBgBitmap = BitmapFactory.decodeResource(getResources(),
                R.mipmap.beauty);
        //设置遮罩图
        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_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;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //画背景
        canvas.drawBitmap(mBgBitmap, 0, 0, null);
        //画灰色
        canvas.drawBitmap(mFgBitmap, 0, 0, null);
    }
}

你可能感兴趣的:(自定义view,xfermode,刮刮卡,PorterDuff)