SurfaceView的特性是:可以在主线程之外的线程中向屏幕绘图上。这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度。在游戏开发中多用到SurfaceView,游戏中的背景、人物、动画等等尽量在画布canvas中画出。
1.案例一
布局文件:
<?xml?version="1.0"?encoding="utf-8"?> <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"? android:orientation="vertical"?android:layout_width="fill_parent" ?? ?android:layout_height="fill_parent"?android:weightSum="1"> ? ? <SurfaceView? android:layout_height="220dip" android:layout_gravity="center"? android:id="@+id/surface"? android:layout_weight="0.25"? android:layout_width="320dip"> </SurfaceView> ? ? <LinearLayout android:id="@+id/linearLayout1"? android:layout_height="wrap_content" android:layout_width="fill_parent"> ? ? ? ? <Button? android:text="播放"? android:id="@+id/button1"? android:layout_width="wrap_content"? android:layout_height="wrap_content"> </Button> ? ? ?? <Button? android:text="暂停"? android:id="@+id/button2"? android:layout_width="wrap_content"? android:layout_height="wrap_content"> </Button> ? ? ?? <Button? android:text="停止"? android:id="@+id/button3"? android:layout_width="wrap_content"? android:layout_height="wrap_content"> </Button> ?? </LinearLayout> </LinearLayout>
主程序:
public?class?SurfaceActivity?extends?Activity?implements?SurfaceHolder.Callback?{ ?? ? ? ? /**?Called?when?the?activity?is?first?created.?*/ ? ? ? ? ?MediaPlayer?player; ? ? ? ? ?SurfaceView?surface; ? ?? ? ? SurfaceHolder?surfaceHolder; ? ?? ? ? Button?play,pause,stop; ? ?? ? ? @Override ?? ? ? ? public?void?onCreate(Bundle?savedInstanceState)?{ ? ? ? ? ? ? super.onCreate(savedInstanceState); ? ? ? ? ? ? ? setContentView(R.layout.main); ? ? ? ?? ? ? ?play=(Button)findViewById(R.id.button1); ? ? ? ? ? ? ? pause=(Button)findViewById(R.id.button2); ? ? ? ? ? ? ? stop=(Button)findViewById(R.id.button3); ? ? ? ?? ? ? ? surface=(SurfaceView)findViewById(R.id.surface); ? ? ?? ? ? ? ? surfaceHolder=surface.getHolder();//SurfaceHolder是SurfaceView的控制接口 ? ? ? ? ? ? ? surfaceHolder.addCallback(this);?//因为这个类实现了SurfaceHolder.Callback接口,所以回调参数直接this ? ? ? ?? ? ? ?surfaceHolder.setFixedSize(320,?220);//显示的分辨率,不设置为视频默认 ? ? ? ?? ? ? ?surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//Surface类型 ? ? ? ? ? ? ? ?play.setOnClickListener(new?OnClickListener(){ ? ? ? ? ?? ? ? ? ? @Override ? ? ? ? ?? ? ? ? ?public?void?onClick(View?v)?{ ? ? ? ? ? ? ?? ? ? ? ?player.start(); ? ? ? ? ?? ? ? ? ?}}); ? ? ? ? ? ? ?pause.setOnClickListener(new?OnClickListener(){ ? ? ?? ? ? ? ? ? ?@Override ? ? ? ? ? ? ? ? ? public?void?onClick(View?v)?{ ? ? ? ?? ? ? ? ? ? ? ?player.pause(); ? ? ? ? ?? ? ? ? ?}}); ? ? ? ?? ? ? ? stop.setOnClickListener(new?OnClickListener(){ ? ? ?? ? ? ? ? ? ? @Override ? ? ? ? ? ? ? ? ? public?void?onClick(View?v)?{ ? ? ? ? ? ? ? ? ? ? ?player.stop(); ? ? ? ? ? ? ? ? ? }}); ? ? ? ? ?} ? ?? ? ? ?@Override ? ? ? ? ?public?void?surfaceChanged(SurfaceHolder?arg0,?int?arg1,?int?arg2,?int?arg3)?{ ? ? ? ? ?} ? ?? ? ? ?@Override ? ?? ? ? public?void?surfaceCreated(SurfaceHolder?arg0)?{? ? ? //必须在surface创建后才能初始化MediaPlayer,否则不会显示图像 ? ? ? ? ? ? ?player=new?MediaPlayer(); ? ? ? ? ? ? ? player.setAudioStreamType(AudioManager.STREAM_MUSIC); ? ? ? ? ? ?player.setDisplay(surfaceHolder); ? ? ?? ? ? ? //设置显示视频显示在SurfaceView上 ? ? ? ? ?? ? ? ? try?{ ? ? ? ? ? ? ?? ? ? ? player.setDataSource("/sdcard/3.mp4"); ? ? ? ?? ? ? ? ? ? ? player.prepare(); ? ? ? ? ? ?? ? ? }?catch?(Exception?e)?{ ? ? ? ? ? ?? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? ?} ? ? ? ? ?} ? ? ? ? ? @Override ? ?? ? ? public?void?surfaceDestroyed(SurfaceHolder?arg0)?{ ? ? ? ? ? ? ?//?TODO?Auto-generated?method?stub ?? ? ? ? ?} ? ? ? ? ? @Override????protected?void?onDestroy()?{ ? ? ?? ? ? ? //?TODO?Auto-generated?method?stub ? ? ?? ? ? ? super.onDestroy(); ? ? ? ? ? ? ?if(player.isPlaying()){ ? ? ? ? ? ? ?player.stop();????????} ? ? ? ? ? ? ?player.release(); ? ? ?? ? ? ? //Activity销毁时停止播放,释放资源。不做这个操作,即使退出还是能听到视频播放的声音? ? ? ? ? }? ? ? }
2.案例二
布局文件main.xml
<?xml?version="1.0"?encoding="utf-8"?>? <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android" ? ?? android:orientation="vertical" ? ?? android:layout_width="fill_parent" ? ?? android:layout_height="fill_parent" ? ?? android:background="#ffffff" ? ?? >? <TextView ?? ? ?android:layout_width="wrap_content" ? ?? android:layout_height="wrap_content" ? ? android:text="@string/filename" ? ?? />? <EditText ? android:layout_width="fill_parent" ? ?? android:layout_height="wrap_content" ? ? android:text="oppo.mp4" ? ? android:id="@+id/filename" ? ? />? <LinearLayout ? ?? android:orientation="horizontal" ? ? android:layout_width="fill_parent" ? android:layout_height="wrap_content" ? ? > ? ?? <ImageButton ? android:layout_width="wrap_content" ? android:layout_height="fill_parent" ? ? ? android:src="@drawable/play" ? ?? ? ?android:id="@+id/play" ? ? /> ? ? <ImageButton ? android:layout_width="wrap_content" ?? android:layout_height="fill_parent" ? ?? ? ?android:src="@drawable/pause" ? ? ? ?? android:id="@+id/pause" ? ?? /> ? ? <ImageButton ?? android:layout_width="wrap_content" ?? android:layout_height="fill_parent" ? ?? ? ?android:src="@drawable/stop" ? ? ? android:id="@+id/stop" ? ? /> ?? <ImageButton ? android:layout_width="wrap_content" ?? android:layout_height="fill_parent" ? ? android:src="@drawable/reset" ? ? ?? android:id="@+id/reset" ?? />? </LinearLayout>? <SurfaceView ? android:layout_width="fill_parent" ? ? ? android:layout_height="fill_parent" ? ? ? android:id="@+id/surfaceview" ?? />? </LinearLayout>
主程序VodeoPlayActivity.java
public?class?VodeoPlayActivity?extends?Activity?{ ?? ? /**?Called?when?the?activity?is?first?created.?*/ ? ? ? private?EditText?filenamEditText; ? ? private?MediaPlayer?mediaPlayer; ? ? ? private?String?filename; ? ? ? private?SurfaceView?surfaceView; ? ? ? private?final?static?String?TAG="VodeoPlayActivity"; ? ? private?int?prosition=0; ? ? ? ? ? @Override ? ? ? public?void?onCreate(Bundle?savedInstanceState)?{ ? ? ? super.onCreate(savedInstanceState); ? ?? ? setContentView(R.layout.main); ? ? ? ? ? filenamEditText=(EditText)?this.findViewById(R.id.filename); ? ? ? surfaceView=(SurfaceView)this.findViewById(R.id.surfaceview); ? ? ?? ? surfaceView.getHolder().setFixedSize(176,?144);//设置分辨率 ? ? ?? ? surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置surfaceview不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前 ? ?? ? surfaceView.getHolder().addCallback(new?SurceCallBack());//对surface对象的状态进行监听 ? ? ? ? mediaPlayer=new?MediaPlayer(); ? ? ? ? ?? ? ButtonOnClikListiner?buttonOnClikListinero=new?ButtonOnClikListiner(); ? ? ? ? ImageButton?start=(ImageButton)?this.findViewById(R.id.play); ? ? ? ?? ? ImageButton?pause=(ImageButton)?this.findViewById(R.id.pause); ? ? ? ? ? ImageButton?stop=(ImageButton)?this.findViewById(R.id.stop); ? ? ? ? ? ImageButton?replay=(ImageButton)?this.findViewById(R.id.reset); ? ? ? ? start.setOnClickListener(buttonOnClikListinero); ? ?? ? pause.setOnClickListener(buttonOnClikListinero); ? ?? ? stop.setOnClickListener(buttonOnClikListinero); ? ? ? ? replay.setOnClickListener(buttonOnClikListinero); ? ? ? } ? ? ? ? private?final?class?ButtonOnClikListiner?implements?View.OnClickListener{ ? ? ? ? @Override ? ? ? public?void?onClick(View?v)?{ ? ? ? if(Environment.getExternalStorageState()==Environment.MEDIA_UNMOUNTED){ ? ? ?? ? Toast.makeText(VodeoPlayActivity.this,?"sd卡不存在",?Toast.LENGTH_SHORT).show(); ? ? ? ? ? ?? ? return; ? ? ?? ? } ? ? ? ?? ? filename=filenamEditText.getText().toString(); ? ? ? ?? ? switch?(v.getId())?{ ? ? ? ?? ? case?R.id.play: ? ? ? ? ? ?? ? play(); ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case?R.id.pause: ? ? ? ? ? ? if(mediaPlayer.isPlaying()){ ? ? ?? ? mediaPlayer.pause(); ? ? ? ? ? ? ? }else{ ? ? ? ? ? ? ? ? ?? ? mediaPlayer.start(); ? ? ? ?? ? } ? ? ? ? ? ? ? ?? ? break; ? ? ? ? ? ? case?R.id.reset: ? ? ? ?? ? if(mediaPlayer.isPlaying()){ ? ? ? mediaPlayer.seekTo(0); ? ? ? ? ? ?? ? }else{ ? ? ? ? ? ? ? ? play(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ?? ? break; ? ? ? ? ? ? ? case?R.id.stop: ? ? ? ? ? ? if(mediaPlayer.isPlaying()){ ? ? ? mediaPlayer.stop(); ? ? ? ? ? ?? ? } ? ? ? ? ? ? ?? ? break; ? ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? ? } ? ? ?? ? private?void?play()?{ ? ?? ? try?{ ? ? ? ? ? ? ? ? ? File?file=new?File(Environment.getExternalStorageDirectory(),filename); ? ? ? ? ? mediaPlayer.reset();//重置为初始状态 ? ? ? ?? ? mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);//设置音乐流的类型 ? ? ? ? ? ? ? mediaPlayer.setDisplay(surfaceView.getHolder());//设置video影片以surfaceviewholder播放 ? ? ?? ? mediaPlayer.setDataSource(file.getAbsolutePath());//设置路径 ? ? ? ? ? ?? ? mediaPlayer.prepare();//缓冲 ? ? ? ? ? ? ? ? ? mediaPlayer.start();//播放 ? ? ? ? ? ? ? }?catch?(Exception?e)?{ ? ? ? ?? ? Log.e(TAG,?e.toString()); ? ? ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? } ? ?? ? } ? ? ? ? private?final?class?SurceCallBack?implements?SurfaceHolder.Callback{ ? ? ? /**?????????*?画面修改?????????*/ ? ? ? ? ? @Override ? ? ? ? ? public?void?surfaceChanged(SurfaceHolder?holder,?int?format,?int?width, int?height)?{ ? ? //?TODO?Auto-generated?method?stub ? ? ? ? ? ? ? ? ? } ? ? ?? ? /**?????????*?画面创建?????????*/ ? ?? ? @Override ? ? ? ? ? public?void?surfaceCreated(SurfaceHolder?holder)?{ ? ? ? ? ?? ? if(prosition>0&&filename!=null){ ? ? ? ? ? ? ? play(); ? ? ? ? ? ? ?? ? mediaPlayer.seekTo(prosition); ? ? ? ? ? ? ? prosition=0;????????????} ? ? ? ? ? ? } ? ? ? ? /**?????????*?画面销毁?????????*/ ? ? ? ? ? @Override ? ? ? ? ? public?void?surfaceDestroyed(SurfaceHolder?holder)?{ ? ? ? ? if(mediaPlayer.isPlaying()){ ? ? ? ? ? prosition=mediaPlayer.getCurrentPosition(); ? ? ? ? ? ? mediaPlayer.stop(); ? ? ? ?? ? } ? ? ? ? ? } ? ? ? }? ? }