Android自定義View-刮刮卡效果

首先來看一下效果圖:(這是醫(yī)生的書《Android群英傳》中的一個知識點)
我的 CSDN地址

刮刮卡效果

 涉及到的知識點
 1. [2D繪圖基礎](http://blog.csdn.net/zone_/article/details/70456348)
 2. PorterDuffXfermode

繪制思路:

  1. 繪制兩個圖層逼泣,第一層繪制想要顯示的圖案扛点,第二層繪制遮罩層(這兩個圖層中渴庆,是第二個圖層覆蓋第一個圖層)
  2. 讓手指滑過的地方變成透明咸灿,就可以看到第一層的圖片了挣输。

第一步:繪制兩個圖層

先來看一下第一步繪制好之后的效果:

這里寫圖片描述

首先是初始化一些數(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)系我進行修改立肘,以免誤導別人。謝謝名扛。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谅年,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肮韧,更是在濱河造成了極大的恐慌融蹂,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弄企,死亡現(xiàn)場離奇詭異超燃,居然都是意外死亡,警方通過查閱死者的電腦和手機拘领,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門意乓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人约素,你說我怎么就攤上這事届良。” “怎么了圣猎?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵伙窃,是天一觀的道長。 經(jīng)常有香客問我样漆,道長,這世上最難降的妖魔是什么晦闰? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任放祟,我火速辦了婚禮,結果婚禮上呻右,老公的妹妹穿的比我還像新娘跪妥。我一直安慰自己,他們只是感情好声滥,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布眉撵。 她就那樣靜靜地躺著侦香,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纽疟。 梳的紋絲不亂的頭發(fā)上罐韩,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天,我揣著相機與錄音污朽,去河邊找鬼散吵。 笑死,一個胖子當著我的面吹牛蟆肆,可吹牛的內(nèi)容都是我干的矾睦。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼炎功,長吁一口氣:“原來是場噩夢啊……” “哼枚冗!你這毒婦竟也來了?” 一聲冷哼從身側響起蛇损,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤赁温,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后州藕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體束世,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年床玻,在試婚紗的時候發(fā)現(xiàn)自己被綠了毁涉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡锈死,死狀恐怖贫堰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情待牵,我是刑警寧澤其屏,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站缨该,受9級特大地震影響偎行,放射性物質發(fā)生泄漏。R本人自食惡果不足惜贰拿,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一蛤袒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膨更,春花似錦妙真、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽练般。三九已至,卻和暖如春锈候,著一層夾襖步出監(jiān)牢的瞬間薄料,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工晴及, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留都办,地道東北人。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓虑稼,卻偏偏與公主長得像琳钉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蛛倦,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容