Android項目刮刮獎詳解(三)
前言
上一期我們已經是完成了刮刮卡的準系統,本期就是給我們的項目增加個功能以及美化一番
目標
- 增加功能 使用者刮卡刮到一定程度的時候,清除遮蓋層
- 在遮蓋層放張圖片,增加使用者體驗
增加一個刮完獎回調監聽
實現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線程裡面執行,可能會出現卡頓,當使用者抬起手指的時候,我們就啟動這個計算進程來計算使用者所擦除的像素點
本功能有些複雜,要想看得懂,需要瞭解 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迴圈用來記錄擦除像素點,有些疑問,因為鴻洋大神用的不一樣,鴻洋大神使用的是下面的嵌套迴圈
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
方法之中進行這樣的修改
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(); } });
測試圖