Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android筆記:SurfaceView與SurfaceHolder對象

Android筆記:SurfaceView與SurfaceHolder對象

編輯:關於Android編程

摘要 調試Media播放時,不時用到SurfaceView與SurfaceHolder對象,寫case測試及實際運行效果, 基本上搞清楚這兩個對象的用法及區別 1、SurfaceView public class SurfaceView extends View SurfaceView是視圖(View)的繼承類, 這個視圖裡內嵌了一個專門用於繪制

調試Media播放時,不時用到SurfaceView與SurfaceHolder對象,寫case測試及實際運行效果,
基本上搞清楚這兩個對象的用法及區別


1、SurfaceView
public class SurfaceView extends View
SurfaceView是視圖(View)的繼承類,這個視圖裡內嵌了一個專門用於繪制的Surface。你可以控制這個Surface的格式和尺寸。Surfaceview控制這個Surface的繪制位置。


surface是縱深排序(Z-ordered)的,這表明它總在自己所在窗口的後面。surfaceview提供了一個可見區域,只有在這個可見區域內 的surface部分內容才可見,可見區域外的部分不可見。surface的排版顯示受到視圖層級關系的影響,它的兄弟視圖結點會在頂端顯示。這意味者 surface的內容會被它的兄弟視圖遮擋,這一特性可以用來放置遮蓋物(overlays)(例如,文本和按鈕等控件)。注意,如果surface上面 有透明控件,那麼它的每次變化都會引起框架重新計算它和頂層控件的透明效果,這會影響性能。你可以通過SurfaceHolder接口訪問這個Surface.用getHolder()方法可以得到這個接口。
surfaceview變得可見時,surface被創建;surfaceview隱藏前,surface被銷毀。這樣能節省資源。
如果你要查看 surface被創建和銷毀的時機,可以重載surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。

surfaceview的核心在於提供了兩個線程:UI線程和渲染線程。

這裡應注意:

1> 所有SurfaceView和SurfaceHolder.Callback的方法都應該在UI線程裡調用,一般來說就是應用程序主線程。
渲染線程所要訪問的各種變量應該作同步處理。
2> 由於surface可能被銷毀,它只在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()之間有效,所以要確保渲染線程訪問的是合法有效的surface。

可以在主線程之外的線程中向屏幕繪圖,這樣可以避免畫圖任務繁重的時候造成主線程阻塞,從而提高了程序的反應速度。
在游戲開發中多用到SurfaceView,游戲中的背景、人物、動畫等等盡量在畫布canvas中畫出。

2、SurfaceHolder
public interface SurfaceHolder

顯示一個surface的抽象接口,使你可以控制surface的大小和格式, 以及在surface上編輯像素,和監視surace的改變。

這個接口通常通過SurfaceView類實現。


surface的控制器,用來操縱surface,處理它的Canvas上畫的效果和動畫,控制表面,大小,像素等。
幾個需要注意的方法:
(1)、abstract void addCallback(SurfaceHolder.Callback callback);
// 給SurfaceView當前的持有者一個回調對象。
(2)、abstract Canvas lockCanvas();
// 鎖定畫布,一般在鎖定後就可以通過其返回的畫布對象Canvas,在其上面畫圖等操作了。
(3)、abstract Canvas lockCanvas(Rect dirty);
// 鎖定畫布的某個區域進行畫圖等..因為畫完圖後,會調用下面的unlockCanvasAndPost來改變顯示內容。
// 相對部分內存要求比較高的游戲來說,可以不用重畫dirty外的其它區域的像素,可以提高速度。
(4)、abstract void unlockCanvasAndPost(Canvas canvas);
// 結束鎖定畫圖,並提交改變。


3、SurfaceHolder.Callback
用戶可以實現此接口接收surface變化的消息。當用在一個SurfaceView 中時, 它只在SurfaceHolder.Callback.surfaceCreated()和SurfaceHolder.Callback.surfaceDestroyed()之間有效。設置Callback的方法是SurfaceHolder.addCallback.
實現上一般繼承SurfaceView並實現SurfaceHolder.Callback接口


下面我們舉個例子說明一下這幾個對象的用法:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 package com.test.surfaceview; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Bundle; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class TestsurfaceviewActivity extends Activity { private final static String TAG = "TestsurfaceviewActivity"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.main); setContentView(new MySurfaceView(this)); // 這裡以MySurfaceView作為顯示View } class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback{ private SurfaceHolder holder; private MyThread mThread ; public MySurfaceView(Context context){ super(context); holder = this.getHolder(); //獲取holder對象 holder.addCallback(this); // 添加surface回調函數 mThread = new MyThread(holder); //創建一個繪圖線程 } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub Log.i(TAG,"surfaceChanged is called"); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub Log.i(TAG,"surfaceCreated is called"); mThread.isRun = true; mThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub Log.i(TAG,"surfaceDestroyed is called"); mThread.isRun = false; mThread.stop(); } } class MyThread extends Thread{ private SurfaceHolder holder ; public boolean isRun = false; public MyThread(SurfaceHolder holder){ this.holder = holder; isRun = true; Log.i(TAG,"MyThread set surface holder"); } @Override public void run(){ Canvas canvas = null; int count = 0; while (isRun) { try { synchronized (holder) { canvas = holder.lockCanvas();// 鎖定畫布,一般在鎖定後就可以通過其返回的畫布對象Canvas,在其上面畫圖等操作了。 canvas.drawColor(Color.BLACK);// 設置畫布背景顏色 Paint p = new Paint(); // 創建畫筆 p.setColor(Color.RED); Rect r = new Rect(500, 200, 300, 250); canvas.drawRect(r, p); canvas.drawText("這是第" + (count++) + "秒", 300, 310, p); Thread.sleep(1000);// 睡眠時間為1秒 } } catch (Exception e) { e.printStackTrace(); } finally { if (canvas != null) { holder.unlockCanvasAndPost(canvas);// 結束鎖定畫圖,並提交改變。 } } } } } }

在Media 播放過程中會需要用到兩個SurfaceView,一個用於繪制顯示界面,另外一個用於播放視頻的顯示

首先在main.xml中定義兩個SurfaceView:

android:id="@+id/playSurface"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

android:id="@+id/mainSurface"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />


然後使用的片斷代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 private SurfaceView mUIView; private SurfaceView mPlayView; private MyMediaplayerManager mPlayManager; mUIView = (SurfaceView)findViewById(R.id.mainSurface); mSurfaceHolder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub } @Override public void surfaceCreated(final SurfaceHolder holder) { // TODO Auto-generated method stub } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } }); mPlayView = (SurfaceView)findViewById(R.id.playSurface); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); holder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder holder) { mPlayManager.setDisplay(holder); // 這裡設置video視頻的顯示Holder } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub } }); // 設定SurfaceView的顯示zorder序 mUIView.setZOrderMediaOverlay(true); mPlayView.setZOrderMediaOverlay(false);

view 可看作就是一個圖層,以上使用兩個圖層,一個是圖形層,另一個是視頻層,需要播放視頻時只需要將圖形層透明掉即可。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved