Android開發:SurfaceView基本用法總結,androidsurfaceview
本文主要講解如何使用SurfaceView,旨在協助大家快速上手SurfaceView開發。由於上篇文章《Android開發:SurfaceView基本用法總結及開發問題分享》 排版不佳,所以另起一篇單獨介紹SurfaceView的基本用法總結。
轉載請註明作者xiong_it和連結:http://blog.csdn.net/xiong_it/article/details/45966309,謝謝!
SurfaceView基本介紹
1、系統給SurfaceView提供了一個專門繪圖的Surface,嵌入在了SurfaceView視圖層中
2、Surface是儲存畫面資料的地方,它持有一個Canvas對象,也就是說Surface是畫面繪製的地方
3、SurfaceHolder是Surface的管理者,可以控制Surface的格式和大小等
綜上所述:畫面在Surface中繪製完成,在SurfaceView中通過獲得SurfaceHolder的對象,管理並展示Surface的資料內容。
SurfaceView和普通View的區別:
普通view需要在UI線程中更新UI,否則容易造成ANR
SurfaceView是在背景工作執行緒中繪製視圖
SurfaceView基本用法
需要使用SurfaceView的場合:視頻播放,攝像預覽,遊戲開發等。總之,SurfaceView適用於需要頻繁更新UI的場合。
自訂SurfaceView的基本流程:
1、繼承SurfaceView
2、重寫SurfaceView的至少一個構造方法
3、利用getHolder()方法得到SurfaceHolder的引用對象
4、給SurfaceHolder對象添加實現SurfaceHolder.Callback的介面對象
5、重寫Callback的三個方法:surfaceChanged,surfaceCreated,surfaceDestroyed
6、利用SurfaceHolder對象設定Surface的格式
7、利用SurfaceHolder對象設定Surface的類型(Api 11以上已廢棄)
8、利用SurfaceHolder對象設定Surface的大小寬高(可選項)
SurfaceView範例程式碼如下:
// 第一步:繼承SurfaceViewpublic class VideoView extends SurfaceView{private SurfaceCallback mSurfaceCallback;private SurfaceHolder mSurfaceHolder;private Canvas mCanvas;private Panit mPanit;// 第二步:重寫構造方法public VideoView(Context context, AttributeSet attrs) {super(context, attrs);// 第三步:獲得SurfaceHolder對象mSurfaceHolder = this.getSurfaceHolder();// 第四步:添加SurfaceHolder.Callback介面mSurfaceHolder().addCallback(mCallback);// 第六步:設定Surface格式// 參數:PixelFormat中定義的int值,詳細參見PixelFormat.javamSurfaceHolder().setFormat(PixelFormat.RGBA_8888); // 第七步:設定Surface類型// 參數:SURFACE_TYPE_NORMAL:用RAM緩衝原生資料的普通Surface // SURFACE_TYPE_HARDWARE:適用於DMA(Direct memory access )引擎和硬體加速的Surface // SURFACE_TYPE_GPU:適用於GPU加速的Surface // SURFACE_TYPE_PUSH_BUFFERS:表明該Surface不包含原生資料,Surface用到的資料由其他對象提供,// 在Camera映像預覽中就使用該類型的Surface,有Camera負責提供給預覽Surface資料,這樣映像預覽會比較流暢。mSurfaceHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}/** * 第八步:設定Surface的大小寬高(可選) * * 用於外部設定Surface的寬高 * @param videoWidth 設定Surface的寬 * @param videoWidth 設定Surface的高 */public void setVideoLayout(int videoWidth, int videoHeight) {mSurfaceHolder().setFixedSize(videoWidth, videoHeight);}/** * 第五步:實現SurfaceHolder.Callback的介面 * 重寫Callback的三個方法:surfaceChanged,surfaceCreated,surfaceDestroyed */private SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {/** * 在Surface格式和大小發生變化時會被立即調用,可以在這個方法中更新Surface * * @param holder 持有當前Surface的SurfaceHolder對象 * @param format surface的新格式 * @param width surface的新寬度 * @param height surface的新高度 */@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}/** * 在Surface首次建立時被立即調用:獲得焦點時。一般在這裡開啟畫圖的線程。 * @param holder 持有當前Surface的SurfaceHolder對象 */@Overridepublic void surfaceCreated(SurfaceHolder holder) {mPanit = new Panit();//繪製一個向右走的圓圈new Thread() {public void run (){synchronized (mSurfaceHolder) {//獲得Surface的畫布對象mCanvas = mSurfaceHolder.lockCanvas();for (int i; i < 500 ; i++) {//繪製向右的圓圈mCanvas.drawCircle(15, 100, 15, mPanit);try {sleep(500);} catch (Exception e) {e.printStackTrace();}}//釋放畫布對象更新SurfacemSurfaceHolder.unlockAndPost(mCanvas);}}}.start();}/** * 在Surface被銷毀時立即調用:失去焦點時。一般在這將畫圖的線程停止銷毀 * @param holder 持有當前Surface的SurfaceHolder對象 */@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {//TODO};}
首先,我們按照標準步驟自訂了SurfaceView,然後,在Surface建立時開啟了一個線程來繪製一個自左向右走的圓。假如大家把代碼運行起來的話,會發現SurfaceView無法繪製,這是為什麼呢?
因為在設定Surface類型時:
mSurfaceHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//表明該Surface不包含原生資料,Surface用到的資料由其他對象提供
使用 SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS 這種類型時是無法使用mSurfaceHolder.lockCanvas()擷取的Canvas來繪圖的,請注意!
setType還有另外三種類型分別是:
SurfaceHolder.SURFACE_TYPE_NORMAL // 用RAM緩衝原生資料的普通Surface SurfaceHolder.SURFACE_TYPE_HARDWARE //適用於DMA(Direct memory access )引擎和硬體加速的Surface SurfaceHolder.SURFACE_TYPE_GPU //適用於GPU加速的Surface
本文只分享SurfaceView的基本用法,並不涉及原理講解,如需瞭解原理,可以移步:(Google)SurfaceView原理詳解 或者:(百度)SurfaceView原理詳解 。如果開發碰到問題,可以先訪問《Android開發:SurfaceView基本用法總結及開發問題分享》 看看是否碰到和筆者一樣的問題,筆者已在文中給出瞭解決方法,如果你有更好的方法,可以評論分享出來,謝謝。
轉載請註明作者xiong_it和連結:http://blog.csdn.net/xiong_it/article/details/45966309,謝謝合作!