天天看點

【我的Android進階之旅】自定義控件之刮刮卡效果

先附上妹子圖一張

【我的Android進階之旅】自定義控件之刮刮卡效果

android刮刮卡效果原理講解:

刮刮卡其實就是上面有個遮罩層,遮罩層會随着手指的滑動慢慢不可見,我們在記憶體中建立一塊畫布,讓手指的滑動的區域和這塊遮罩層的交集消失不可見即可。 我們這裡讓底部顯示了一張妹子的圖檔,當然也可以是文字或者别的,底部背景是圖檔還是文字我們不需要關心,我們隻需要關心的是這個遮罩層和手勢滑動過的區域的交集處。

畫筆有setXferMode方法,這個是進行圖層混合用到的,請看下圖:

【我的Android進階之旅】自定義控件之刮刮卡效果

我們看下DstIn 和DstOut :

進行混合時底部的圖層為Dst,上層的為Src.在這裡,遮罩層為Dst,手勢走過的路徑為Src.

我們看DstIn,代表取Dst中兩者的交集部分顯示。這個顯然不符合。

我們再看Dstout,代表取Dst中兩者的不相交部分顯示。我們手勢劃過的部分與遮罩層相交(這塊的遮罩層不顯示),沒滑到的地方就不相交,(這塊的遮罩層顯示)。這樣正好符合我們的要求。

上代碼:

/**
 * Time:2019/9/11
 * Author:Jimmy Wang
 * Email:[email protected]
 * Blog:https://blog.csdn.net/wzy901213
 * Description:
 */
public class GuaGuaKaView extends View {
    /**
     * 繪制線條的Paint,即使用者手指繪制Path
     */
    private Paint mOutterPaint = new Paint();
    /**
     * 繪制遮罩層Paint
     */
    private  Paint mPaint = new Paint();
    /**
     * 記錄使用者繪制的Path
     */
    private Path mPath = new Path();
    /**
     * 美女背景圖
     */
    private Bitmap mBitmap;
    /**
     * 遮罩層目标背景圖
     */
    private Bitmap mDstBitmap;
    /**
     * 記憶體緩存的Canvas
     */
    Canvas mCanvas ;

    private int mLastX,mLastY;

    public GuaGuaKaView(Context context) {
        super(context);
    }

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

    private void init() {
        mBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.beauty);
        mOutterPaint.setColor(Color.RED);
        mOutterPaint.setAntiAlias(true);
        mOutterPaint.setDither(true);
        mOutterPaint.setStyle(Paint.Style.STROKE);
        mOutterPaint.setStrokeJoin(Paint.Join.ROUND); // 圓角
        mOutterPaint.setStrokeCap(Paint.Cap.ROUND); // 圓角
        // 設定畫筆寬度
        mOutterPaint.setStrokeWidth(50);
        mOutterPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mDstBitmap = Bitmap.createBitmap(getMeasuredWidth(),getMeasuredHeight() ,Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mDstBitmap);
        mCanvas.drawColor(Color.GRAY);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(mBitmap,0,0, mPaint);
        canvas.drawBitmap(mDstBitmap,0,0, mPaint);
        drawPath();
    }


    /**
     * 繪制線條
     */
    private void drawPath()
    {
        mCanvas.drawPath(mPath, mOutterPaint);
    }

    @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;
    }
}

           

寫在最後:

如果這裡的遮蓋層是妹子的衣服,然後背景是個沒穿衣服的妹子,我們不停滑的話會怎樣,真不敢想象