源 起
最近在寫一個類似“圍住神經貓”的應用,現在需要給一個可以移動的Paint元素指定一張圖片,如下圖,要把黃點改成其他圖片;
Paint所在的類繼承於SurfaceView,SurfaceView可以直接從內存等硬件接口獲取圖像數據,速度很快;然后再implements 一個OnTouchListener接口來監聽觸摸事件;
過 程
最初找到很多方法,給playground添加圖片、給Activity添加圖片、另寫一個工具類加載圖片。。。都很繁瑣,而且代碼加進去運行的時候總是Crash,可能是自己操作存在問題,這些方法都沒有實現想要的效果;
后來發現,只需要在redraw() 函數中添加幾行代碼~
圖像繪制函數redraw() 的代碼是這樣寫的,功能是設置路障圓點、路徑圓點和一個移動圓點的顏色:
public void redraw(){ // 繪制
Canvas c = getHolder().lockCanvas(); //c.drawColor(Color.LTGRAY); // 繪制淺灰色背景界面
c.drawColor(Color.DKGRAY); // 繪制淺灰色背景界面 //c.drawBitmap(resizeBitmap(xrd, getWidth(), getHeight()), 0, 0, null);// 設置背景圖片s
size = (ROW / 3) * (getWidth() / 9 - WIDTH);// 將格子向下平移 // 繪制所有的點到Activity
Paint paint = new Paint(); // 開啟畫面抗鋸齒,必須寫在點生成之前
paint.setFlags(Paint.ANTI_ALIAS_FLAG); for (int i = 0; i < ROW-1; i++) { // 進行奇數行\偶數行的判斷
int offset = 0; if (i % 2 != 0) { offset = WIDTH /2; // 偶數行寬度縮進半個點
} for (int j = 0; j < COL-1; j++) { Dot one = getDot(j, i); switch (one.getStatus()) { case Dot.STATUS_OFF: //paint.setColor(0xFFEEEEEE);// 完全不透明,顏色淺灰色 //paint.setColor(Color.GRAY);// 淺灰色
paint.setColor(Color.rgb(165, 165, 165)); // 設定好顏色之后,開始在 canvas上面繪制, RectF是繪制 橢圓,循環繪制100個
c.drawOval(new RectF(one.getX()*WIDTH+offset, one.getY()*WIDTH, //右側邊界
(one.getX()+1)*WIDTH+offset, (one.getY()+1)*WIDTH), paint); break; case Dot.STATUS_ON: // 路障顏色 //paint.setColor(0xFFFFAA00); // 0xFF透明度 FFAA00黃色
paint.setColor(Color.rgb(147, 117, 27));
c.drawOval(new RectF(one.getX()*WIDTH+offset, one.getY()*WIDTH, //右側邊界
(one.getX()+1)*WIDTH+offset, (one.getY()+1)*WIDTH), paint); break; case Dot.STATUS_IN:
paint.setColor(Color.YELLOW); c.drawOval(new RectF(one.getX()*WIDTH+offset, one.getY()*WIDTH, //右側邊界
(one.getX()+1)*WIDTH+offset, (one.getY()+1)*WIDTH), paint); // paint.setColor(getResources().getColor(android.R.color.black));
break; default: break; } } }
現在只需在redraw()函數的 case Dot.STATUS_IN: 之下寫入如下幾行代碼即可:
Resources res = getResources(); Bitmap bmp = BitmapFactory.decodeResource(res, R.drawable.happy_huge); Rect rect = new Rect(0, bmp.getHeight(), bmp.getWidth(), 0); c.drawBitmap(bmp,null, new RectF(one.getX()*WIDTH+offset, one.getY()*WIDTH, (one.getX()+1)*WIDTH+offset, (one.getY()+1)*WIDTH), paint);
記得圖片要先加載到drawable中,這里已把圖片處理為透明的png格式;
這段代碼的原理是:實例化一個Resources,通過Bitmap讀取Resources和R.drawable,然后使用Rect類設定范圍,再通過Canvas的drawBitmap()函數繪制出來就可以了~
按下Ctrl+F11;
接下來就是見證奇跡的時刻~
有 待 完 善
需求已然實現,目前將近500行代碼,不過我打算繼續實現如下效果:
1、自定義難易度;
2、圍住之后彈窗加載一張圖片;
3、把移動的元素改成動態gif。
BTW:
雖然我一次就把他圍住了,但那是因為自己了解代碼算法的緣故,否則是無法一次性圍住的,不過可以增加隨機性,這樣就算了解算法也無法百分百圍住,搭配漫畫表情更增新趣味~