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

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

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

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

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

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

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

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

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

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

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

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

2016412145144865.png (1024×654)

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

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

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

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

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

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

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

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

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

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

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

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

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

2016412145237293.gif (356×299)

我們提供了四個(gè)按鈕,可以進(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 通過(guò)SurfaceView/SurfaceHolder實(shí)現(xiàn)自己的播放器 
 * @author chenzheng_java 
 * @since 2011/03/23 
 * @description 這里進(jìn)行一下補(bǔ)充說(shuō)明,我們可以通過(guò)mediaplayer添加OnPreparedListener 
 * 以及OnCompletionListener等事件對(duì)準(zhǔn)備好播放以及播放完成后的操作進(jìn)行控制。 
 * 使用SurfaceView以及SurfaceHolder進(jìn)行視頻播放時(shí),結(jié)構(gòu)是這樣的: 
 * 1、首先,我們從布局文件中獲取一個(gè)surfaceView 
 * 2、通過(guò)surfaceView.getHolder()方法獲取與該容器想對(duì)應(yīng)的surfaceHolder 
 * 3、對(duì)srufaceHolder進(jìn)行一些默認(rèn)的設(shè)置,如addCallback()和setType() 
 * 4、通過(guò)mediaPlayer.setDisplay()方法將視頻播放與播放容器鏈接起來(lái) 
 */ 
public class MyMediaPlayerActivity extends Activity { 
 
  MediaPlayer mediaPlayer ; // 播放器的內(nèi)部實(shí)現(xiàn)是通過(guò)MediaPlayer 
  SurfaceView surfaceView ;// 裝在視頻的容器 
  SurfaceHolder surfaceHolder;// 控制surfaceView的屬性(尺寸、格式等)對(duì)象 
  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)的那個(gè)的surefaceHolder 
     */ 
    surfaceHolder = surfaceView.getHolder(); 
    /** 
     * 注冊(cè)當(dāng)surfaceView創(chuàng)建、改變和銷毀時(shí)應(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)建一個(gè)push的'surface',主要的特點(diǎn)就是不進(jìn)行緩沖 
     */ 
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
  } 
   
  /*** 
   * @param targetButton 被用戶點(diǎn)擊的按鈕 
   */ 
  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("通知", "播放過(guò)程中出現(xiàn)了錯(cuò)誤哦"); 
    } 
  } 
   
  /** 
   * 暫停 
   */ 
  private void pause(){ 
    Log.i("通知", "點(diǎn)擊了暫停按鈕"); 
    if(isPause==false){ 
      mediaPlayer.pause(); 
      isPause=true; 
    }else{ 
      mediaPlayer.start(); 
      isPause=false; 
    } 
     
     
  } 
   
  /** 
   * 重置 
   */ 
  private void reset(){ 
    Log.i("通知", "點(diǎn)擊了reset按鈕"); 
    // 跳轉(zhuǎn)到視頻的最開始 
    mediaPlayer.seekTo(0); 
    mediaPlayer.start(); 
  } 
   
  /** 
   * 停止 
   */ 
  private void stop(){ 
    Log.i("通知", "點(diǎn)擊了stop按鈕"); 
    mediaPlayer.stop(); 
    mediaPlayer.release(); 
     
  } 
   
} 

相關(guān)文章

最新評(píng)論

石楼县| 武隆县| 广宗县| 广丰县| 罗山县| 凌源市| 安多县| 西盟| 博乐市| 喀什市| 阿拉尔市| 图片| 尖扎县| 崇阳县| 正镶白旗| 织金县| 腾冲县| 阿瓦提县| 永安市| 丹江口市| 桃园县| 集安市| 固镇县| 柳州市| 时尚| 铁力市| 太仆寺旗| 双辽市| 泾阳县| 卫辉市| 临清市| 芒康县| 天台县| 彰武县| 龙陵县| 安吉县| 沧源| 东山县| 桦南县| 余庆县| 长春市|