最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android開發(fā)中的Surface庫及用其制作播放器UI的例子

 更新時間:2016年04月12日 15:01:25   作者:chenzheng_java  
這篇文章主要介紹了Android開發(fā)中的Surface庫及用其制作播放器界面的例子,利用SurfaceView和SurfaceHolder可以高效地繪制和控制圖形界面,需要的朋友可以參考下

1、Surface
1.1、 就如在C語言編程一樣,通過一個文件的句柄,就可以操作文件,獲取文件的內(nèi)容。 同樣的,通過Surface就可以獲取raw buffer其中的內(nèi)容。原生緩沖區(qū)(raw buffer)存儲著當(dāng)前窗口的像素數(shù)據(jù)。

1.2、事實上,當(dāng)?shù)玫揭粋€Surface對象時,同時會得到一個Canvas(畫布)對象。這一點可以通過查看\frameworks\base\core\java\android\view\Surface.java文件可知道Surface類定義了一個Canvas成員變量

private int mSurfaceControl; 
private int mSaveCount; 
private Canvas mCanvas; 
private int mNativeSurface; 
private int mSurfaceGenerationId; 
private String mName; 

1.3、 理解Canvas對象,可以把它當(dāng)做畫布,Canvas的方法大多數(shù)是設(shè)置畫布的大小、形狀、畫布背景顏色等等,要想在畫布上面畫畫,一般要與Paint對象結(jié)合使用,顧名思義,Paint就是畫筆的風(fēng)格,顏料的色彩之類的。

// 創(chuàng)建畫筆  
Paint paint = new Paint();  
paint.setColor(Color.RED);// 設(shè)置紅色  
 
canvas.drawCircle(60, 20, 10, paint);// 畫一個圓  

1.4、Surface本身的作用類似一個句柄,得到了這個句柄就可以得到其中的Canvas、原生緩沖器以及其它方面的內(nèi)容。

1.5、Surface實現(xiàn)了Parcelable接口,(implements Parcelable),也就是說Surface對象可以把顯示內(nèi)容的數(shù)據(jù)寫入到 Parcel 中,并且能夠從Parcel讀回數(shù)據(jù)。

2、SurfaceView
SurfaceView提供了一個專門用于繪制的surface,這個surface內(nèi)嵌于。你可以控制這個Surface的格式和尺寸。Surfaceview控制這個Surface在屏幕的正確繪制位置。
surface是Z-ordered的(也就是說在xyz坐標(biāo)系中,按照Z坐標(biāo)排序的,Z值大的表面覆蓋在Z值小的表面的上方),這表明它總在自己所在窗口的后面。surfaceview在顯示窗口處為Surface提供了一個可見區(qū)域,通過這個區(qū)域,才能看到Surface里面的內(nèi)容??梢苑胖靡恍└采w圖層(overlays)在Surface上面,如Button、Textview之類的。但是,需要注意的是,如果Surface上面有全透明的控件,那么隨著Surface的每一次變化,這些全透明的控件就會重新渲染,這樣的話,就影響性能與顯示的效果。
你可以通過SurfaceHolder這個接口去訪問Surface,而執(zhí)行g(shù)etHolder()方法可以得到SurfaceHolder接口。
當(dāng)SurfaceView的窗口可見時,Surface就會被創(chuàng)建,當(dāng)SurfaceView窗口隱藏時,Surface就會被銷毀。當(dāng)然了,你也可以通過復(fù)寫surfaceCreated(SurfaceHolder) 和 surfaceDestroyed(SurfaceHolder)  這兩個方法來驗證一下Surface何時被創(chuàng)建與何時被銷毀。
SurfaceView提供了一個運行在渲染線程的surface,若你要更新屏幕,你需要了解以下線程知識。
所有SurfaceView 和 SurfaceHolder.Callback的方法都應(yīng)該在主線程(UI線程)里面調(diào)用,應(yīng)該要確保渲染進(jìn)程所訪問變量的同步性。
你必須確保只有當(dāng)Surface有效的時候,(也就是當(dāng)Surface的生命周期在SurfaceHolder.Callback.surfaceCreated() 和SurfaceHolder.Callback.surfaceDestroyed()之間)才能讓渲染進(jìn)程訪問。

2.1、SurfaceView與Surface的聯(lián)系
簡單來說,SurfaceView與Surface的聯(lián)系就是,Surface是管理顯示內(nèi)容的數(shù)據(jù)(implementsParcelable),包括存儲于數(shù)據(jù)的交換。而SurfaceView就是把這些數(shù)據(jù)顯示出來到屏幕上面。
兩者聯(lián)系如圖所示:

2016412145144865.png (1024×654)

3、SurfaceHolder
SurfaceHolder是控制surface的一個抽象接口,你可以通過SurfaceHolder來控制surface的尺寸和格式,或者修改surface的像素,監(jiān)視surface的變化等等,SurfaceHolder是SurfaceView的典型接口。
與直接控制SurfaceView來修改surface不同,使用SurfaceHolder來修改surface時,需要注意lockCanvas() 和Callback.surfaceCreated().這兩個方法。
SurfaceHolder控制surface的流程所使用的幾個方法。

3.1、abstract void    addCallback(SurfaceHolder.Callback callback)
給SurfaceHolder一個回調(diào)對象。

3.2、abstract Canvas    lockCanvas(Rect dirty)
鎖定畫布中的某一個區(qū)域,返回的畫布對象Canvas(當(dāng)更新的內(nèi)容只有一個區(qū)域時,同時要追求高效,可以只更
新一部分的區(qū)域,而不必更新全部畫布區(qū)域)

3.3、abstract Canvas    lockCanvas()
鎖定畫布,返回的畫布對象Canvas

3.4、abstract void    removeCallback(SurfaceHolder.Callback callback)
移除回調(diào)對象

3.5、abstract void    unlockCanvasAndPost(Canvas canvas)
結(jié)束鎖定畫圖,并提交改變。

4、SurfaceHolder.Callback
SurfaceHolder.Callback是監(jiān)聽surface改變的一個接口

4.1、public abstract voidsurfaceChanged(SurfaceHolder holder, int format, int width, int height)
surface發(fā)生改變時被調(diào)用

4.2、public abstract voidsurfaceCreated(SurfaceHolder holder)
在surface創(chuàng)建時被調(diào)用,一般在這個方法里面開啟渲染屏幕的線程。

4.3、public abstract voidsurfaceDestroyed(SurfaceHolder holder)
銷毀時被調(diào)用,一般在這個方法里將渲染的線程停止。

附上上述所說幾種的聯(lián)系方法

SurfaceHolder = SurfaceView.getHolder(); 
 
Surface = SurfaceHolder.getSurface(); 
 
Canvas =SurfaceHolder.LockCanvas(Rect dirty) 
 
Canvas  =Surface.lockCanvas(Rect dirty) 

5、DEMO:通過SurfaceView以及SurfaceHolder進(jìn)行視頻播放
使用AudioView進(jìn)行視頻播放的時候,是不是很不爽,千篇一律的模式,惡心吧。這里,我們可以通過一些方式對MediaPlayer進(jìn)行包裝。而所用到的正是SurfaceView以及SurfaceHolder。
最終效果圖:

2016412145237293.gif (356×299)

我們提供了四個按鈕,可以進(jìn)行播放控制。

布局文件media.xml代碼:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:layout_width="fill_parent" android:layout_height="fill_parent" 
  android:orientation="vertical"> 
  <SurfaceView android:id="@+id/surfaceView1" 
    android:layout_width="320px" android:layout_height="160px"></SurfaceView> 
  <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" 
  android:orientation="horizontal" 
  > 
  <ImageButton android:id="@+id/button_play" android:src="@drawable/play" android:onClick="buttonClick" 
    android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageButton> 
  <ImageButton android:id="@+id/button_pause" android:src="@drawable/pause" android:onClick="buttonClick" 
    android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageButton> 
  <ImageButton android:id="@+id/button_stop" android:src="@drawable/stop" android:onClick="buttonClick" 
    android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageButton> 
  <ImageButton android:id="@+id/button_reset" android:src="@drawable/reset" android:onClick="buttonClick" 
  android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageButton> 
  </LinearLayout>   
</LinearLayout> 

activity代碼:

package cn.com.chenzheng_java.media; 
 
import android.app.Activity; 
import android.media.AudioManager; 
import android.media.MediaPlayer; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
/** 
 * @description 通過SurfaceView/SurfaceHolder實現(xiàn)自己的播放器 
 * @author chenzheng_java 
 * @since 2011/03/23 
 * @description 這里進(jìn)行一下補充說明,我們可以通過mediaplayer添加OnPreparedListener 
 * 以及OnCompletionListener等事件對準(zhǔn)備好播放以及播放完成后的操作進(jìn)行控制。 
 * 使用SurfaceView以及SurfaceHolder進(jìn)行視頻播放時,結(jié)構(gòu)是這樣的: 
 * 1、首先,我們從布局文件中獲取一個surfaceView 
 * 2、通過surfaceView.getHolder()方法獲取與該容器想對應(yīng)的surfaceHolder 
 * 3、對srufaceHolder進(jìn)行一些默認(rèn)的設(shè)置,如addCallback()和setType() 
 * 4、通過mediaPlayer.setDisplay()方法將視頻播放與播放容器鏈接起來 
 */ 
public class MyMediaPlayerActivity extends Activity { 
 
  MediaPlayer mediaPlayer ; // 播放器的內(nèi)部實現(xiàn)是通過MediaPlayer 
  SurfaceView surfaceView ;// 裝在視頻的容器 
  SurfaceHolder surfaceHolder;// 控制surfaceView的屬性(尺寸、格式等)對象 
  boolean isPause ; // 是否已經(jīng)暫停了 
   
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.media); 
    surfaceView = (SurfaceView) findViewById(R.id.surfaceView1); 
    /** 
     * 獲取與當(dāng)前surfaceView相關(guān)聯(lián)的那個的surefaceHolder 
     */ 
    surfaceHolder = surfaceView.getHolder(); 
    /** 
     * 注冊當(dāng)surfaceView創(chuàng)建、改變和銷毀時應(yīng)該執(zhí)行的方法 
     */ 
    surfaceHolder.addCallback(new SurfaceHolder.Callback() { 
       
      @Override 
      public void surfaceDestroyed(SurfaceHolder holder) { 
        Log.i("通知", "surfaceHolder被銷毀了"); 
        if(mediaPlayer!=null) 
        mediaPlayer.release(); 
      } 
       
      @Override 
      public void surfaceCreated(SurfaceHolder holder) { 
        Log.i("通知", "surfaceHolder被create了"); 
      } 
       
      @Override 
      public void surfaceChanged(SurfaceHolder holder, int format, int width, 
          int height) { 
        Log.i("通知", "surfaceHolder被改變了"); 
      } 
    }); 
     
    /** 
     * 這里必須設(shè)置為SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS哦,意思 
     * 是創(chuàng)建一個push的'surface',主要的特點就是不進(jìn)行緩沖 
     */ 
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
  } 
   
  /*** 
   * @param targetButton 被用戶點擊的按鈕 
   */ 
  public void buttonClick(View targetButton){ 
    int buttonId = targetButton.getId(); 
    switch (buttonId) { 
    case R.id.button_play: 
      play(); 
      break; 
    case R.id.button_pause: 
      pause(); 
      break; 
    case R.id.button_reset: 
      reset(); 
      break; 
    case R.id.button_stop: 
      stop(); 
      break; 
    default: 
      break; 
    } 
     
  } 
   
  /** 
   * 播放 
   */ 
  private void play(){ 
     
    mediaPlayer = new MediaPlayer(); 
    // 設(shè)置多媒體流類型 
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
     
    // 設(shè)置用于展示mediaPlayer的容器 
    mediaPlayer.setDisplay(surfaceHolder); 
    try { 
      mediaPlayer.setDataSource("/data/jinsha.3gp"); 
      mediaPlayer.prepare(); 
      mediaPlayer.start(); 
      isPause = false; 
    } catch (Exception e) { 
      Log.i("通知", "播放過程中出現(xiàn)了錯誤哦"); 
    } 
  } 
   
  /** 
   * 暫停 
   */ 
  private void pause(){ 
    Log.i("通知", "點擊了暫停按鈕"); 
    if(isPause==false){ 
      mediaPlayer.pause(); 
      isPause=true; 
    }else{ 
      mediaPlayer.start(); 
      isPause=false; 
    } 
     
     
  } 
   
  /** 
   * 重置 
   */ 
  private void reset(){ 
    Log.i("通知", "點擊了reset按鈕"); 
    // 跳轉(zhuǎn)到視頻的最開始 
    mediaPlayer.seekTo(0); 
    mediaPlayer.start(); 
  } 
   
  /** 
   * 停止 
   */ 
  private void stop(){ 
    Log.i("通知", "點擊了stop按鈕"); 
    mediaPlayer.stop(); 
    mediaPlayer.release(); 
     
  } 
   
} 

相關(guān)文章

  • Android實現(xiàn)圖像切換器

    Android實現(xiàn)圖像切換器

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)圖像切換器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Flutter將整個App變?yōu)榛疑暮唵螌崿F(xiàn)方法

    Flutter將整個App變?yōu)榛疑暮唵螌崿F(xiàn)方法

    Flutter?是?Google?開源的?UI?工具包,幫助開發(fā)者通過一套代碼庫高效構(gòu)建多平臺精美應(yīng)用,這篇文章主要給大家介紹了關(guān)于Flutter將整個App變?yōu)榛疑膶崿F(xiàn)方法,在Flutter中實現(xiàn)整個App變?yōu)榛疑欠浅:唵蔚?需要的朋友可以參考下
    2021-12-12
  • 超簡單Android集成華為HMS Scankit 掃碼SDK實現(xiàn)掃一掃二維碼

    超簡單Android集成華為HMS Scankit 掃碼SDK實現(xiàn)掃一掃二維碼

    這篇文章主要介紹了超簡單Android集成華為HMS Scankit 掃碼SDK實現(xiàn)掃一掃二維碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Kotlin如何安全訪問lateinit變量的實現(xiàn)

    Kotlin如何安全訪問lateinit變量的實現(xiàn)

    這篇文章主要介紹了Kotlin如何安全訪問lateinit變量的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • cocos2d-2.0-x-2.0.3 交叉編譯到android報錯解決

    cocos2d-2.0-x-2.0.3 交叉編譯到android報錯解決

    我用的是cocos2d-2.0-x-2.0.3 之前弄了一天也沒成功 今天來了下載了最新的ndk8 更新了sdk 又重新是了一遍 居然成功了,不知道是工具的版本問題還是哪一步出錯誤了,在這里詳細(xì)的整理一下,感興趣的朋友可以了解下
    2013-01-01
  • Android多線程處理機制中的Handler使用介紹

    Android多線程處理機制中的Handler使用介紹

    本文將為大家介紹下Android的Handler的使用方法,Handler可以發(fā)送Messsage和Runnable對象到與其相關(guān)聯(lián)的線程的消息隊列,感興趣的朋友可以了解下哈
    2013-06-06
  • Android實現(xiàn)簡易版彈鋼琴效果

    Android實現(xiàn)簡易版彈鋼琴效果

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)簡易版彈鋼琴效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • Android貝塞爾曲線實現(xiàn)手指軌跡

    Android貝塞爾曲線實現(xiàn)手指軌跡

    這篇文章主要為大家詳細(xì)介紹了Android貝塞爾曲線實現(xiàn)手指軌跡效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • Android使用Intent實現(xiàn)頁面跳轉(zhuǎn)

    Android使用Intent實現(xiàn)頁面跳轉(zhuǎn)

    這篇文章主要為大家詳細(xì)介紹了Android使用Intent實現(xiàn)頁面跳轉(zhuǎn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評論

东明县| 丹寨县| 循化| 巨鹿县| 鄯善县| 深州市| 仁化县| 永春县| 松溪县| 城市| 奎屯市| 长治市| 宜兰市| 什邡市| 大渡口区| 清水县| 凌海市| 广宗县| 乌拉特前旗| 珲春市| 无棣县| 安国市| 彭泽县| 阿克| 合水县| 新邵县| 多伦县| 茶陵县| 达尔| 运城市| 日土县| 若羌县| 宁蒗| 濮阳市| 宁都县| 正定县| 同江市| 吉木萨尔县| 肥乡县| 加查县| 渝北区|