一、Surface
Surface在SDK的文檔中的描述是這樣的:Handle onto a raw buffer that is being managed by the screen compositor,Android中的Surface就是一個用來畫圖形(graphics)或圖像(image)的地方,對於View及其子類,都是畫在Surface上,各Surface對象通過Surfaceflinger合成到frameBuffer,每個Surface都是雙緩沖,它有一個backBuffer和一個frontBuffer,Surface中創建了Canvas對象,用來管理Surface繪圖操作,Canvas對應Bitmap,存儲Surface中的內容。流程為:
1:創建一個Bitmap對象。
2:創建一個Canvas對象關聯創建的Bitmap對象。
3:在Canvas上進行繪制。
4:鎖定Canvas畫布。
5:將Bitmap內容繪制到backBuffer中去。
6:解鎖Canvas畫布。
二、SurfaceView
SurfaceView是視圖類View的子類,且實現了Parcelable接口且實現了Parcelable接口,其中內嵌了一個專門用於繪制的Surface,SurfaceView可以控制這個Surface的格式和尺寸,以及Surface的繪制位置。可以理解為Surface就是管理數據的地方,SurfaceView就是展示數據的地方。
三、SurfaceHolder
SurfaceHolder是一個接口,類似於一個surace的監聽器。通過下面三個回調方法監聽Surface的創建、銷毀或者改變。
SurfaceView中調用getHolder方法,可以獲得當前SurfaceView中的surface對應的SurfaceHolder,SurfaceHolder中重要的方法有:
1: abstract void addCallback(SurfaceHolder.Callback callback );為SurfaceHolder添加一個SurfaceHolder.Callback回調接口。
2: abstract Canvas lockCanvas() ;獲取Surface中的Canvas對象,並鎖定之。所得到的Canvas對象。
3:abstract void unlockCanvasAndPost(Canvas canvas);當修改Surface中的數據完成后,釋放同步鎖,並提交改變,然后將新的數據進行展示。
四、SurfaceHolder.Callback
SurfaceHolder.Callback是SurfaceHolder接口內部的靜態子接口,SurfaceHolder.Callback中定義了三個接口方法:
1:public void sufaceChanged(SurfaceHolder holder,int format,int width,int height){}//Surface的大小發生改變時調用。
2: public void surfaceCreated(SurfaceHolder holder){}//Surface創建時激發,一般在這里調用畫面的線程。
3: public void surfaceDestroyed(SurfaceHolder holder){}//銷毀時激發,一般在這里將畫面的線程停止、釋放。
SurfaceView和View最本質的區別在於:SurfaceView是在一個新起的單獨線程中可以重新繪制畫面而View必須在UI的主線程中更新畫面。
public class MySurfaceView extends SurfaceView implements Runnable, Callback { private SurfaceHolder mHolder; // 用於控制SurfaceView private Thread t; // 聲明一條線程 private volatile boolean flag; // 線程運行的標識,用於控制線程 private Canvas mCanvas; // 聲明一張畫布 private Paint p; // 聲明一支畫筆 float m_circle_r = 10; public MySurfaceView(Context context) { super(context); mHolder = getHolder(); // 獲得SurfaceHolder對象 mHolder.addCallback(this); // 為SurfaceView添加狀態監聽 p = new Paint(); // 創建一個畫筆對象 p.setColor(Color.WHITE); // 設置畫筆的顏色為白色 setFocusable(true); // 設置焦點 } /** * 當SurfaceView創建的時候,調用此函數 */ @Override public void surfaceCreated(SurfaceHolder holder) { t = new Thread(this); // 創建一個線程對象 flag = true; // 把線程運行的標識設置成true t.start(); // 啟動線程 } /** * 當SurfaceView的視圖發生改變的時候,調用此函數 */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } /** * 當SurfaceView銷毀的時候,調用此函數 */ @Override public void surfaceDestroyed(SurfaceHolder holder) { flag = false; // 把線程運行的標識設置成false mHolder.removeCallback(this); } /** * 當屏幕被觸摸時調用 */ @Override public boolean onTouchEvent(MotionEvent event) { return true; } /** * 當用戶按鍵時調用 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { surfaceDestroyed(mHolder); return super.onKeyDown(keyCode, event); } @Override public void run() { while (flag) { try { synchronized (mHolder) { Thread.sleep(100); // 讓線程休息100毫秒 Draw(); // 調用自定義畫畫方法 } } catch (InterruptedException e) { e.printStackTrace(); } finally { if (mCanvas != null) { mHolder.unlockCanvasAndPost(mCanvas);//結束鎖定畫圖,並提交改變。 } } } } /** * 自定義一個方法,在畫布上畫一個圓 */ protected void Draw() { mCanvas = mHolder.lockCanvas(); // 獲得畫布對象,開始對畫布畫畫 if (mCanvas != null) { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.BLUE); paint.setStrokeWidth(10); paint.setStyle(Style.FILL); if (m_circle_r >= (getWidth() / 10)) { m_circle_r = 0; } else { m_circle_r++; } Bitmap pic = ((BitmapDrawable) getResources().getDrawable(R.drawable.qq)).getBitmap(); mCanvas.drawBitmap(pic, 0, 0, paint); for (int i = 0; i < 5; i++) for (int j = 0; j < 8; j++) mCanvas.drawCircle((getWidth() / 5) * i + (getWidth() / 10), (getHeight() / 8) * j + (getHeight() / 16), m_circle_r, paint); } } }
