各位童鞋請你們注意:surfaceview中確實有onDraw這個方法,但是你surfaceview不會自己去調用!!!
而我代碼中的ondraw() 也好draw() 也好,都是我自己定義的一個方法。。。放線上程中不斷調用的,一定要注意!!
之前我們對view和surfaceview 做了比較和取捨,最後我們發現surfaceview更加的適合運作與遊戲開發中,那麼下面就讓我們來看看這個surfaceview的結構吧;
先上一段代碼:
/**
*
*/
package com.himi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
import android.view.animation.Animation;
/**
* @author Himi
*/
public class MySurfaceView extends SurfaceView implements Callback, Runnable {// 備忘1
private SurfaceHolder sfh;
private Thread th;
private Canvas canvas;
private Paint paint;
private int ScreenW, ScreenH;
public MySurfaceView(Context context) {
super(context);
th = new Thread(this);
sfh = this.getHolder();
sfh.addCallback(this); // 備忘1
paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
this.setKeepScreenOn(true);// 保持螢幕常亮
}
@Override
public void startAnimation(Animation animation) {
super.startAnimation(animation);
}
public void surfaceCreated(SurfaceHolder holder) {
ScreenW = this.getWidth();// 備忘2
ScreenH = this.getHeight();
th.start();
}
private void draw() {
try {
canvas = sfh.lockCanvas(); // 得到一個canvas執行個體
canvas.drawColor(Color.WHITE);// 刷屏
canvas.drawText("Himi", 100, 100, paint);// 畫文字文本
canvas.drawText("這就是簡單的一個遊戲架構", 100, 130, paint);
} catch (Exception ex) {
} finally { // 備忘3
if (canvas != null)
sfh.unlockCanvasAndPost(canvas); // 將畫好的畫布提交
}
}
public void run() {
while (true) {
draw();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
}
代碼很簡單,我們繼承繼承surfaceview類,並且使用回調callback介面以及線程runnable介面。那麼這裡我簡單的說下Callback介面和SurfaceHolder 類的作用;
//備忘1
callback介面:
只要繼承SurfaceView類並實現SurfaceHolder.Callback介面就可以實現一個自訂的SurfaceView了,SurfaceHolder.Callback在底層的Surface狀態發生變化的時候通知View,SurfaceHolder.Callback具有如下的介面:
•surfaceCreated(SurfaceHolder holder):當Surface第一次建立後會立即調用該函數。程式可以在該函數中做些和繪製介面相關的初始化工作,一般情況下都是在另外的線程來繪製介面,所以不要在這個函數中繪製Surface。
•surfaceChanged(SurfaceHolder holder, int format, int width,int height):當Surface的狀態(大小和格式)發生變化的時候會調用該函數,在surfaceCreated調用後該函數至少會被調用一次。
SurfaceHolder 類:
它是一個用於控制surface的介面,它提供了控制surface 的大小,格式,上面的像素,即監視其改變的。
SurfaceView的getHolder()函數可以擷取SurfaceHolder對象,Surface 就在SurfaceHolder對象內。雖然Surface儲存了當前視窗的像素資料,但是在使用過程中是不直接和Surface打交道的,由SurfaceHolder的Canvas lockCanvas()或則Canvas lockCanvas()函數來擷取Canvas對象,通過在Canvas上繪製內容來修改Surface中的資料。如果Surface不可編輯或則尚未建立調用該函數會返回null,在unlockCanvas() 和lockCanvas()中Surface的內容是不緩衝的,所以需要完全重繪Surface的內容,為了提高效率只重繪變化的部分則可以調用lockCanvas(Rect rect)函數來指定一個rect地區,這樣該地區外的內容會緩衝起來。在調用lockCanvas函數擷取Canvas後,SurfaceView會擷取Surface的一個同步鎖直到調用unlockCanvasAndPost(Canvas canvas)函數才釋放該鎖,這裡的同步機制保證在Surface繪製過程中不會被改變(被摧毀、修改)。
// 備忘2
我沒有在該surfaceview的初始化函數中將其ScreenW 與ScreenH 進行賦值,這裡要特別注意,如果你在初始化調用ScreenW = this.getWidth();和ScreenH = this.getHeight();那麼你將得到很失望的值 全部為0;原因是和介面Callback介面機制有關,當我們繼承callback介面會重寫它的surfaceChanged()、surfaceCreated()、surfaceDestroyed(),這幾個函數當surfaceCreated()被執行的時候,真正的view才被建立,也就是說之前得到的值為0 ,是因為初始化會在surfaceCreated()方法執行以前執行,view沒有的時候我們去取螢幕寬高肯定是0,所以這裡要注意這一點;
//備忘3
這裡我把draw的代碼都try起來,主要是為了當畫的內容中一旦拋出異常了,那麼我們也能 在finally中執行該操作。這樣當代碼拋出異常的時候不會導致Surface出去不一致的狀態。
其實這就是一個簡單的遊戲架構了,當然還少了按鍵處理,聲音播放等等,這些我後續會寫出相關的學習文章。對於surfaceview的介紹差不多就介紹到這裡了,其中的理解是看了別人的文章和自己的理解、當然可能理解的會有些偏差,但是我想不會太離譜 呵呵。
本文出自 “Himi” 部落格,請務必保留此出處http://xiaominghimi.blog.51cto.com/2614927/605697