- 浏览: 465806 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
bewithme:
我把一个透明背景的PNG画到了另外一张图片上,为啥透明背景就变 ...
Java绘制PNG图片时的黑色背景问题 -
davidwkj:
Y坐标的公式不对。算出来的值是错的!!!!!!!!!!!!!! ...
两条线段是否相交,计算交点公式。 -
zhang9181156:
茅塞顿开哈,感谢
android--相机开发 -
leecinwell:
哈
Android条用照相机,实现可剪切功能 -
life_菜鸟飞:
非常感谢作者这么详细的讲解,自己也动手实践了一下,发现前面几个 ...
android--相机开发
一、Surface
Surface就是“表面”的意思。在SDK的文档中,对Surface的描述是这样的:“Handle onto a raw buffer that is being managed by the screen compositor”,翻译成中文就是“由屏幕显示内容合成器(screen compositor)所管理的原生缓冲器的句柄”,这句话包括下面两个意思:
1. 通过Surface(因为Surface是句柄)就可以获得原生缓冲器以及其中的内容。就像在C语言中,可以通过一个文件的句柄,就可以获得文件的内容一样;
2. 原生缓冲器(rawbuffer)是用于保存当前窗口的像素数据的。
引伸地,可以认为Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方。根据Java方面的常规知识,我们知道通常画图是在一个Canvas对象上面进行的,由此,可以推知一个Surface对象中应该包含有一个Canvas对象,事实上的确如此,而且这一点可以很容易通过debug运行程序的方式得到证明(将光标停留在对象变量surface上,会弹出一个对话框,其中红色方框的内容,就表面surface中有一个CompatileCanvas成员变量)当然,看源代码也是可以证明这一点:
因此,在前面提及的两个意思的基础上,可以再加上一条:
3. Surface中有一个Canvas成员,专门用于画图的。
所以,Surface中的Canvas成员,是专门用于供程序员画图的场所,就像黑板一样;其中的原生缓冲器是用来保存数据的地方;Surface本身的作用类似一个句柄,得到了这个句柄就可以得到其中的Canvas、原生缓冲器以及其它方面的内容。
二、SurfaceView
SurfaceView,顾名思义就是Surface的View,通过SurfaceView就可以看到Surface的部分或者全部的内容,下面用一个图来形象地描述一下Surface和SurfaceView的关系:
也就是说,Surface是用通过SurfaceView才能展示其中的内容。从这个意思上来说,SurfaceView中的View之确切的含义应该是viewport即“视口”的意思,做过数据库设计的朋友知道,假定一个数据表有20个字段,但我们常常只用到其中的5个字段,那么就可以在原数据表的基础上,通过SQL语句CREATEVIEW来创建只包含那5个字段内容的view。
另一方面,SurfaceView是Android中View的子类。事实上,在Android中所有用于界面展示的类皆为View的子类,包括那些不可见的、各种各样的Layout。
所以说,SurfaceView中的View有两个含义:
1. 视口(viewport)的意思
2. SurfaceView是View的派生类
在Android中Surface是从Object派生而来,且实现了Parcelable接口。看到Parcelable就让人能很自然地想到数据容器,SurfaceView就是用来展示Surface中的数据的。在这个层面上而言,Surface就是管理数据的地方,SurfaceView就是展示数据的地方。
三、SurfaceHolder
SurfaceHolder是一个接口,其作用就像一个关于Surface的监听器。提供访问和控制SurfaceView背后的Surface 相关的方法 (providingaccess and control over this SurfaceView's underlying surface),它通过三个回调方法,让我们可以感知到Surface的创建、销毁或者改变。在SurfaceView中有一个方法getHolder,可以很方便地获得SurfaceView所对应的Surface所对应的SurfaceHolder(有点拗口吧)。
除下面将要提到的SurfaceHolder.Callback外,SurfaceHolder还提供了很多重要的方法,其中最重要的就是:
1. abstract void addCallback(SurfaceHolder.Callbackcallback)
为SurfaceHolder添加一个SurfaceHolder.Callback回调接口。
2. abstract CanvaslockCanvas()
获取一个Canvas对象,并锁定之。所得到的Canvas对象,其实就是Surface中一个成员。
3. abstract CanvaslockCanvas(Rectdirty)
同上。但只锁定dirty所指定的矩形区域,因此效率更高。
4. abstract void unlockCanvasAndPost(Canvascanvas)
当修改Surface中的数据完成后,释放同步锁,并提交改变,然后将新的数据进行展示,同时Surface中相关数据会被丢失。
5. public abstract void setType (int type)
设置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数据,这样图像预览会比较流畅。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。需要注意的是,在高版本的Android SDK中,setType这个方法已经被depreciated了。
2、3、4中的同步锁机制的目的,就是为了在绘制的过程中,Surface中的数据不会被改变。
从设计模式的高度来看,Surface、SurfaceView和SurfaceHolder实质上就是广为人知的MVC,即Model-View-Controller。Model就是模型的意思,或者说是数据模型,或者更简单地说就是数据,也就是这里的Surface;View即视图,代表用户交互界面,也就是这里的SurfaceView;SurfaceHolder很明显可以理解为MVC中的Controller(控制器)。这样看起来三者之间的关系就清楚了很多。
四、SurfaceHolder.Callback
前面已经讲到SurfaceHolder是一个接口,它通过回到方法的方式,让我们可以感知到Surface的创建、销毁或者改变。其实这一点是通过其内部的静态子接口SurfaceHolder.Callback来实现的。SurfaceHolder.Callback中定义了三个接口方法:
1. abstract void surfaceChanged(SurfaceHolderholder, int format, int width, int height)
当surface发生任何结构性的变化时(格式或者大小),该方法就会被立即调用。
2. abstract void surfaceCreated(SurfaceHolderholder)
当surface对象创建后,该方法就会被立即调用。
3. abstract void surfaceDestroyed(SurfaceHolderholder)
当surface对象在将要销毁前,该方法会被立即调用。
在Android SDK文档中,关于SurfaceView的描述里面,有一段这样的话:
One of the purposes of this class is to provide a surface in which a secondarythread can render into the screen. If you are going to use it this way, youneed to be aware of some threading semantics:
- All SurfaceView and SurfaceHolder.Callbackmethods will be called from the thread running the SurfaceView's window(typically the main thread of the application). They thus need to correctlysynchronize with any state that is also touched by the drawing thread.
- You must ensure that the drawingthread only touches the underlying Surface while it is valid -- betweenSurfaceHolder.Callback.surfaceCreated() andSurfaceHolder.Callback.surfaceDestroyed().
这段话很重要,大致意思如下:
这个类的目的之一,就是提供一个可以用另外一个线程(第二个线程)进行屏幕渲染的surface(译注:即UI线程和绘制线程可以分离)。如果你打算这样使用,那么应当注意一些线程方面的语义:
- 所有SurfaceView和SurfaceHolder.Callback中声明的方法,必须在运行SurfaceView窗口中的线程中调用(典型地,就是应用的主线程。译注:即UI线程),因为它们需要正确地将同时被绘制线程访问的各种状态进行同步。
- 必须保证,只有在背后的Surface有效的时候 – 在SurfaceHolder.Callback.surfaceCreated()和 SurfaceHolder.Callback.surfaceDestroyed()这两个方法调用之间,访问它。
下面,我们通过一个非常简单例子来实际感受一下(代码摘自http://www.cnblogs.com/xuling/archive/2011/06/06/android.html,并做了一些结构性的改动),请留意代码中的注释:
1. 在Eclipse中创建一个Android Project项目TestSurfaceView,并选择生成缺省的Activity TestSurfaceViewActivity
2. 创建一个绘制线程如下:
- <span style="font-size:11px;">
- package com.pat.testsurfaceview;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- importandroid.view.SurfaceHolder;
- // 绘制线程
- public class MyThread extendsThread
- {
- private SurfaceHolder holder;
- private boolean run;
- publicMyThread(SurfaceHolder holder)
- {
- this.holder = holder;
- run = true;
- }
- @Override
- public void run()
- {
- int counter = 0;
- Canvascanvas = null;
- while(run)
- {
- // 具体绘制工作
- try
- {
- // 获取Canvas对象,并锁定之
- canvas= holder.lockCanvas();
- // 设定Canvas对象的背景颜色
- canvas.drawColor(Color.WHITE);
- // 创建画笔
- Paintp = new Paint();
- // 设置画笔颜色
- p.setColor(Color.BLACK);
- // 设置文字大小
- p.setTextSize(30);
- // 创建一个Rect对象rect
- Rectrect = new Rect(100, 50, 380, 330);
- // 在canvas上绘制rect
- canvas.drawRect(rect,p);
- // 在canvas上显示时间
- canvas.drawText("Interval = " + (counter++) + " seconds.", 100, 410, p);
- Thread.sleep(1000);
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- finally
- {
- if(canvas != null)
- {
- // 解除锁定,并提交修改内容
- holder.unlockCanvasAndPost(canvas);
- }
- }
- }
- }
- public boolean isRun()
- {
- return run;
- }
- public void setRun(boolean run)
- {
- this.run = run;
- }
- }</span>
3. 自定义一个SurfaceView类如下:
- <span style="font-size:11px;">
- package com.pat.testsurfaceview;
- import android.content.Context;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- public class MySurfaceView extends SurfaceView
- implements
- SurfaceHolder.Callback
- {
- private SurfaceHolder holder;
- private MyThread myThread;
- publicMySurfaceView(Context context)
- {
- super(context);
- // 通过SurfaceView获得SurfaceHolder对象
- holder = getHolder();
- // 为holder添加回调结构SurfaceHolder.Callback
- holder.addCallback(this);
- // 创建一个绘制线程,将holder对象作为参数传入,这样在绘制线程中就可以获得holder
- // 对象,进而在绘制线程中可以通过holder对象获得Canvas对象,并在Canvas上进行绘制
- myThread = new MyThread(holder);
- }
- // 实现SurfaceHolder.Callback接口中的三个方法,都是在主线程中调用,而不是在绘制线程中调用的
- @Override
- public voidsurfaceChanged(SurfaceHolder holder, int format, int width, int height)
- {
- }
- @Override
- public voidsurfaceCreated(SurfaceHolder holder)
- {
- // 启动线程。当这个方法调用时,说明Surface已经有效了
- myThread.setRun(true);
- myThread.start();
- }
- @Override
- public void surfaceDestroyed(SurfaceHolderholder)
- {
- // 结束线程。当这个方法调用时,说明Surface即将要被销毁了
- myThread.setRun(false);
- }
- }</span>
4. 修改TestSurfaceViewActivity.java代码,使之如下:
- <span style="font-size:11px;">
- package com.pat.testsurfaceview;
- import android.app.Activity;
- import android.os.Bundle;
- public class TestSurfaceViewActivity extends Activity
- {
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- //setContentView(R.layout.main);
- setContentView(new MySurfaceView(this));
- }
- }</span>
运行结果:
很显然,我们可以在MyThread的run方法中,做很多更有意思的事情。弄清楚了Surface、SurfaceView、SurfaceHolder和SurfaceHolder.Callback这些概念,以及它们之间的关系,对我们更好地使用它们应该会有相当大的帮助。
发表评论
-
浅析android应用增量升级
2013-05-29 13:31 2688背景 随着android应用体积的不断增大 ... -
Activity是如何生成一个 view 的
2013-05-16 11:09 1325Activity是一个工人,它来控制Window;Windo ... -
Android 获取新浪天气预报数据
2012-12-07 13:07 3017新浪天气预报地址: http://php.weathe ... -
Android连接网络问题
2012-11-23 11:14 1946一、检查网络是否连接 方法一、 publ ... -
Android异步下载图片并且缓存图片到本地
2012-09-06 16:21 1881转来的,以备不时之需!! 在Android开发中 ... -
Android条用照相机,实现可剪切功能
2012-08-12 12:35 4533public class CameraActivity ... -
android--相机开发
2012-08-10 08:17 11480在android中应用相机功能,一般有两种:一种是直接调 ... -
15个令人震惊的HTML5效果
2012-07-04 10:09 131215个令人震惊的HTML5效果 除非你一直 ... -
Android 读写文件的N种写法
2012-07-04 09:54 1083Android 读写文件的N种写法(待续。。。) ... -
如何干掉360(付代码)
2012-06-29 16:09 1346最近360很凶,有推送的,有桌面图标的,全部会被提示有风 ... -
Cocos2d-x跨Android&iOS平台开发入门
2012-06-26 10:22 1510好吧,确实存在这 ... -
解决Android加载图片时内存溢出的问题
2012-06-18 13:52 46304尽量不要使用setImageBitmap或setImag ... -
android 代码 混淆
2012-06-04 10:22 20401、得到 classes.dex文件;直接用你机器上的 ... -
android代码混淆是出现Conversion to Dalvik format failed with error 1的解决方法
2012-06-04 10:18 4471最近做android项目,给代码混淆时遇到问题,在项目加入混淆 ... -
Re-installation failed解决方法
2011-12-27 22:49 4792我的方法:去模拟器卸载上次安装的*.apk ... -
Failed to install *.apk on device 'emulator-5554': timeout
2011-12-20 00:31 9290错误提示: Failed to inst ... -
android 中的 Bitmap
2011-12-20 00:32 3914在Android SDK中说明可以支持的图片格式如下:p ... -
Android 小球重力感应实现
2011-12-16 20:49 1618重力感应主要是依靠手机的加速度传感器(acceleromete ... -
Android中资源文件夹res/raw和assets的使用
2011-12-16 20:37 9537*res/raw和assets的相同点: 1.两者目录 ... -
为不同分辨率的手机创建界面
2011-12-16 20:36 14441,首先进入res 文件夹下。 2,创建一个名为“la ...
相关推荐
一个丢西瓜的例子,可以对surfaceSurface、SurfaceHolder及SurfaceHolder.Callback有所理解
项目经理Android笔记及网上收集的试题 使用Android系统进行拍照用到的类有:(D) A. SurfaceView B. SurfaceHolder C.Callback D. Camera
import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;public class DecodeActivity extends Activity implements SurfaceHolder.Callback { // private static final ...
SurfaceView + MediaPlayer 实现的视频播放器,支持横竖屏切换,手势快进快退、调节音量,亮度等。------代码简单,基础应用
GameView整个程序最主要的类,是主游戏的界面,该界面继承自SurfaceView并实现了SurfaceHolder.Callback接口,其中包含了一个刷帧的线程类。 GuiZe象棋的规则类,其他类通过调用canMove方法给出起始位置与结束...
implements SurfaceHolder.Callback { SurfaceView surfaceView; Surface surface; ndcam.Device camera; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate...
并为SurfaceView的SurfaceHolder添加Callback监听器。 3、调用MediaPlayer对象的setDisplay(Surfaceolder sh)将所播放的视频图像输出到指定的SurfaceView组件 4、调用MediaPlayer对象的start()、stop()、和pause...
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } decodeFormats = null; characterSet = null; playBeep = true; AudioManager audioService = (AudioManager) getSystemService...
首先要继承SurfaceView,实现SurfaceHolder.Callback接口。 重写方法:surfaceChanged:surface大小或格式发生变化时触发,在surfaceCreated调用后该函数至少会被调用一次。 surfaceCreated:Surface创建时触发,...
public class MySurfaceView extends SurfaceView implements Callback, Runnable { public MySurfaceView(Context context, AttributeSet attrs) { super(context, attrs); sfh = this.getHolder(); sfh....
这里我们直接继承SurfaceView,实现SurfaceHolder.Callback接口,处理surfaceCreated、surfaceChanged以及surfaceDestroyed方法,这里我们并没有把按键控制传入,最终游戏的控制方面仍然由View内部类处理比较好,...
public class DistinguishActivity extends BaseActivity implements SurfaceHolder.Callback, Camera.PictureCallback { private ImageView iv_ivPhoto; private SurfaceView surfaceView; private ...
Class ScrollTextView extends SurfaceView implements SurfaceHolder.Callback Android 滚动字幕,如新闻联播下面的,可以使用在广告机,机顶盒,电视App等信息发布系统。 以前是在信息发布系统上使用过,作为动态...
Step2:在界面布局文件中定义SurfaceView控件,或在程序中创建SurfaceView控件,并为SurfaceView的SurfaceHolder添加Callback监听器; Step3:调用MediaPlayer对象的setDisney(SurfaceHolder sh)方法将所播放的视频...
本文记录了用自定义Camera...public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback { private SurfaceHolder mHolder; private Camera mCamera; priva
网上介绍SurfaceView的用法有很多,写法也层出不同,例如继承SurfaceView类,或者继承SurfaceHolder.Callback类等,这个可以根据功能实际需要自己选择,我这里就直接在普通的用户界面调用SurfaceHolder的lockCanvas...
网上介绍SurfaceView的用法有很多,写法也层出不同,例如继承SurfaceView类,或者继承SurfaceHolder.Callback类等,这个可以根据功能实际需要自己选择,本文所述方法就直接在普通的用户界面调用SurfaceHolder的...
(1): 这里新建一个绘图ChartView,继承SurfaceView并实现SurfaceHolder.Callback , Runnable接口,主要绘图工作在子线程中完成。 (2):现实 SurfaceHolder.Callback接口的三个方法,并在 surfaceCreated中开启子线程...
代码如下:class surface extends SurfaceView implements SurfaceHolder.Callback { SurfaceHolder sfholder; Camera camera; Bitmap bitmap; public surface(Context context) { super(context); // TODO ...