上一期咱們已是完成了刮刮卡的基本功能,本期就是給咱們的項目增長個功能以及美化一番java
增長一個刮完獎回調監聽canvas
咱們首先來了解一下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
修飾,通俗的講就是加了個鎖,防止併發出現錯誤
可能你們對這個功能很不屑,認爲本身以前不是會了嗎,其實沒有那麼簡單,我本身嘗試的時候都出現了錯誤,通過搜索資料嘗試才達到效果。
先說下我遇到的問題
第一個問題,咱們能夠經過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);
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(); } });