Android項目刮刮獎詳解(四)

Android項目刮刮獎詳解(三)html

前言

上一期咱們已是完成了刮刮卡的基本功能,本期就是給咱們的項目增長個功能以及美化一番java

目標

  • 增長功能 用戶刮卡刮到必定程度的時候,清除遮蓋層
  • 在遮蓋層放張圖片,增長用戶體驗
  • 增長一個刮完獎回調監聽canvas

    實現

    1.自動消除效果

    咱們首先來了解一下bitmap的getPixels方法數組

    getPixels(@ColorInt int[] pixels, int offset, int stride,int x, int y, int width, int height)

    getPixels()函數把一張圖片,從指定的偏移位置(offset),指定的位置(x,y)截取指定的寬高(width,height ),把所得圖像的每一個像素顏色轉爲int值,存入pixels。
    至於參數stride,查了資料,發現看不太懂,因而即是沒有繼續深究,咱們直接用就是了併發

咱們須要一個線程來完成咱們的計算像素,由於計算不能一直在UI線程裏面執行,可能會出現卡頓,當用戶擡起手指的時候,咱們就啓動這個計算進程來計算用戶所擦除的像素點ide

本功能有些複雜,要想看得懂,須要瞭解 UI線程更新View的知識和java中進程部分知識,推薦看一下這篇子進程更新UI函數

private Runnable mRunnable = new Runnable() {
    int[] pixels;

    @Override
    public void run() {

        int w = mBitmap.getWidth();
        int h = mBitmap.getHeight();

        float wipeArea = 0;//擦除像素點計數,初始爲0
        float totalArea = w * h;//所有的像素點

        pixels = new int[w * h];
        /**
         * pixels   接收位圖顏色值的數組
         * offset   寫入到pixels[]中的第一個像素索引值
         * stride   pixels[]中的行間距個數值(必須大於等於位圖寬度)。能夠爲負數
         * x      從位圖中讀取的第一個像素的x座標值。
         * y      從位圖中讀取的第一個像素的y座標值
         * width    從每一行中讀取的像素寬度
         * height    讀取的行數
         */
        Bitmap b = mBitmap;
        b.getPixels(pixels, 0, w, 0, 0, w, h);

       //for循環查找用戶擦除的像素點,爲0則是擦除,wipeArea+1
        for (int i = 0; i < totalArea; i++) {
            if (pixels[i] == 0) {
                wipeArea++;
            }
        }
        //
        if (wipeArea > 0 && totalArea > 0) {
            int percent = (int) (wipeArea * 100 / totalArea);//計算比例
            if (percent > 50) {
                isClear = true;//isClear是以前聲明的全局變量,
                postInvalidate();//子進程中調用此方法重繪View
            }
        }

    }
};

上述代碼中有個for循環用來記錄擦除像素點,有些疑問,由於鴻洋大神用的不同,鴻洋大神使用的是下面的嵌套循環post

for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                int index = i + j * w;
                if (pixels[index] == 0) {
                    wipeArea++;
                }
            }
        }

以後咱們還須要改寫代碼,首先,是在觸摸事件中增長咱們對用戶擡起手指的操做測試

case MotionEvent.ACTION_UP:
            new Thread(mRunnable).start();
            break;

以後,經過isClear這個變量來控制是否畫出路徑,onDraw方法之中進行這樣的修改this

protected void onDraw(Canvas canvas) {
        canvas.drawText(message,mBitmap.getWidth()/2-mBackground.width()/2,getMeasuredHeight()/2+mBackground.height()/2,messagePaint);
        if (!isClear){
            drawPath();
            canvas.drawBitmap(mBitmap, 0,0, null);
        }
    }

當canvas寫出了文字,以後就不畫遮蓋層了,這樣即是達到了清除遮蓋層的效果

這裏須要注意一下if中的條件,還要,isClear還得用volatile修飾,通俗的講就是加了個鎖,防止併發出現錯誤

2.遮蓋層繪製圖片

可能你們對這個功能很不屑,認爲本身以前不是會了嗎,其實沒有那麼簡單,我本身嘗試的時候都出現了錯誤,通過搜索資料嘗試才達到效果。
先說下我遇到的問題

  • 圖片只顯示一部分
  • 畫筆清除不了圖片,畫的時候出現黑色的筆跡

第一個問題,咱們能夠經過Bitmap的靜態方法來解決

public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,boolean filter)

傳入一個須要調整大小的bitmap對象,以後,長度和高度,最後一個參數傳入true
background = Bitmap.createScaledBitmap(background,width,height,true);//對bitmap進行縮放

第二個問題,由於咱們使用的是雙緩衝技術繪圖,因此,咱們須要將遮蓋層的圖片先繪製在mBitmap中去
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//以得到的寬高建立一個32位的bitmap
mCanvas = new Canvas(mBitmap);
mCanvas.drawBitamap(background,0,0,null);

3.回調接口

public interface onGuaCompleteListener{
        void complete();
    }
    private onGuaCompleteListener mlistener;

    public void setGuaCompleteListener(onGuaCompleteListener mlistener) {
        this.mlistener = mlistener;
    }

以後在onDraw方法裏添加回調

protected void onDraw(Canvas canvas) {
        Log.d(TAG, "onDraw: 畫");
        canvas.drawText(message,mBitmap.getWidth()/2-mBackground.width()/2,getMeasuredHeight()/2+mBackground.height()/2,messagePaint);
        if (!isClear){
            drawPath();
            canvas.drawBitmap(mBitmap, 0,0, null);

        }else if (mlistener!=null){
            mlistener.complete();
        }
    }

當畫到百分之60的時候,就會將isClear的值變爲true,同時,就會進入到else if中,回調完成刮獎的接口

咱們到MainActivity中設置監聽器來監聽刮刮卡的完成操做,彈出一個Toast或者是對話框,我這裏簡單起見就直接彈出一個Toast

GuajiangView mView = (GuajiangView) findViewById(R.id.view);
    mView.setGuaCompleteListener(new GuajiangView.onGuaCompleteListener() {
        @Override
        public void complete() {
            Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT).show();
        }
    });

測試圖

相關文章
相關標籤/搜索