【Android遊戲開發之三】剖析 SurfaceView ! Callback以及SurfaceHolder!!

來源:互聯網
上載者:User

 

各位童鞋請你們注意: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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.