Android开发:SurfaceView基本用法总结

本文主要讲解如何使用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示例代码如下:

// 第一步:继承SurfaceView
public 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.java
		mSurfaceHolder().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的新高度
		 */
		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

		}

		/**
		 * 在Surface首次创建时被立即调用:获得焦点时。一般在这里开启画图的线程。
		 * @param holder 持有当前Surface的SurfaceHolder对象
		 */
		@Override
		public 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();
							}
						}
						//释放画布对象更新Surface
						mSurfaceHolder.unlockAndPost(mCanvas);
						}
					}
			}.start();
		}

		/**
		 * 在Surface被销毁时立即调用:失去焦点时。一般在这将画图的线程停止销毁
		 * @param holder 持有当前Surface的SurfaceHolder对象
		 */
		@Override
		public 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的基本用法,并不涉及原理讲解,如需了解原理,可以移步:(谷歌)SurfaceView原理详解 或者:(百度)SurfaceView原理详解 。如果开发碰到问题,可以先访问Android开发:SurfaceView基本用法总结及开发问题分享 看看是否碰到和笔者一样的问题,笔者已在文中给出了解决方法,如果你有更好的方法,可以评论分享出来,谢谢。

转载请注明作者xiong_it和链接:http://blog.csdn.net/xiong_it/article/details/45966309,谢谢合作!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。