一 : SurfaceHolder.Callback
一前文概要说明
首先得简单说明一下Surface与SurfaceHolder.Callback之间的联系。
Surface是android的一个重要元素,用于android画面的图形绘制。而SurfaceView是视图(View)的一个继承类,每一个SurfaceView都内嵌封装一个Surface。通过调用SurfaceHolder可以调用SurfaceView,控制图形的尺寸和大小。而SurfaceHolder是通过getholder()来取得。创立SurfaceHolder对象后,用SurfaceHolder.Callback()来回调SurfaceHolder,对SurfaceView进行控制。
单纯得用文字表述有点绕,因此下面将给出几段代码以供理解。
SurfaceHolderholder=((SurfaceView)findViewById(R.id.cameraPreview)).getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
这样就可以通过callback()对SurfaceView进行修改。
二callback()方法介绍
callback()包括三个函数:
①surfaceCreated(SurfaceHolderholder)
当Surface第一次创建后会立即调用该函数。程序可以在该函数中做些和绘制界面相关的初始化工作,一般情况下都是在另外的线程来绘制界面,所以不要在这个函数中绘制Surface。
参数
holdersurface所创建的SurfaceHolder
②surfaceChanged(SurfaceHolderholder, int format, int width, int height)
当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次。
参数
holder 更新surface的SurfaceHolder
format 新的图形格式
width 新的宽度
height 新的高度
③surfaceDestroyed()
当Surface被摧毁前会调用该函数,该函数被调用后就不能继续使用Surface了,一般在该函数中来清理使用的资源。
参数
holder所要被删除的surface的SurfaceHolder
二 : SurfaceHolder
SurfaceHolder
版本:Android 2.2 r1
结构
继承关系
public interface SurfaceHolder
android.view.SurfaceHolder
概述
抽象接口持有人显示表面。(www.61k.com]允许您控制面的大小和格式,编辑在suface的橡树,并监测到变化。此接口通常可通过SurfaceView类来实现。
当一个线程使用不同于正在运行的线程的SurfaceView的接口时,你应该仔细阅读lockCanvas()和Callback.surfaceCreated()这两个抽象函数
常量值
public static final int SURFACE_TYPE_GPU
常数已声明不赞成使用,已过时。
被忽略,该常量值在需要时自动设置。
Surface类型:创建适用于GPU加速的Surface
常量值:2 (0x00000002)
public static final int SURFACE_TYPE_HARDWARE
常数已声明不赞成使用,已过时。
被忽略,该常量值在需要时自动设置。
Surface类型:创建适用于DMA(Direct memory access )引擎和硬件加速的Surface 常量值:1 (0x00000001)
public static final int SURFACE_TYPE_NORMAL
Surface类型:创建用RAM缓存原生数据的普通Surface
常量值:0 (0x00000000)
public static final int SURFACE_TYPE_PUSH_BUFFERS
Surface类型:创建一个不包含原生数据Surface,Surface用到的数据由其他对象提供。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了,否则将出现错误。 常量值:3 (0x00000003)
公共方法
public abstract void addCallback (SurfaceHolder.Callback callback)
给Surface持有者添加回调接口,一个持有者可以关联多个回调接口。
参数
callback 新的回调接口
surfaceholder SurfaceHolder
public abstract Surface getSurface ()
直接获取Surface对象,这个Surface对象并不总是能获取的。(www.61k.com]
例如:当使用SurfaceView, Surface的持有者直到该View隶属于当前窗口管理器,确认布局大小和屏幕的位置后才进行创建,你通常需要实现Callback.surfaceCreated寻找出可用的Surface。
注意,如果你通过另外的线程直接访问Surface ,关键在于你正确的实现了Callback.surfaceCreated 和Callback.surfaceDestroyed 函数来确保你访问的线程的Surface是可用的,有效的,当一个线程正在使用该Surface,将不能得到释放,销毁。
这个方法的目的是用于经常需要直接访问Surface对象的框架(通常是通过本地代码),在设计API时总使用SurfaceHolder来改变Surface,而不是Surface对象本身。一个经验规则是应用程序代码不能调用该方法
返回
Surface对象
public abstract Rect getSurfaceFrame ()
检索当前Surface的大小
注意:不能修改发挥矩形区域大小,这是唯一安全的调用从SurfaceView的窗口线程,否则就需要放在lockCanvas()里面调用。
返回
Suface的矩形尺寸,左侧和顶部总为0
public abstract boolean isCreating ()
使用这个方法是来确定在进程中的Surface是否通过Callback方法正被创建,这是为了确定surfaceChanged(SurfaceHolder, int, int, int).方法是否能用。
返回
True 进程里的Suface正被创建
public abstract Canvas lockCanvas ()
开始编辑surface的像素,返回可以用来画到表面的位图的Canvas。如果表面尚未建立或无法进行编辑将返回null。通常需要实现Callback.surfaceCreated找出Surface时方可使用。
Surface的内容再从调用unlockCanvas() 和 lockCanvas(),之间被保存,为此,在Surface区域内的没有个像素都将被画出,仅一个例外是当脏矩形被指定的时候,非脏像素将会被保存。 如果当Surface没有初始化(Callback.surfaceCreated之前或者Callback.surfaceDestroyed之后),你反复调用它,为了避免耗费CPU,这些调用将以缓慢的速度被杀死。
如果没有返回null值,这个函数在内部直到调用unlockCanvasAndPost(Canvas)函数,才持有锁,来防止SurfaceView在绘制的时候被创建,销毁,或者修改surface,因为当调用Callback.surfaceDestroyed你不需要创建一个特殊的同步绘制线程 所以你能更方便的直接访问这个Sufrace
返回
用来进行绘制的Canvas
surfaceholder SurfaceHolder
public abstract Canvas lockCanvas (Rect dirty)
和lockCanvas()一样,但允许指定一个脏矩形,再这个矩形的每个像素都必须被绘制,脏矩形外的像素将被保存直到下次调用lockCanvas()。[www.61k.com]
参数
dirty 将被修改的Surface区域
返回
用来进行绘制的Canvas
参见
lockCanvas ()
public abstract void removeCallback (SurfaceHolder.Callback callback)
从Surface持有者中删除先前添加的回调接口
参数
callback 要删除的回调接口
public abstract void setFixedSize (int width, int height)
使surface固定大小,他将永远不能该表大小,当和SurfaceView一起工作时,这必须被同一运行的SurfaceView的窗口线程来调用
参数
width surface的宽.
height surface的高.
public abstract void setFormat (int format)
设置surface所需的像素格式。默认是不透明的,当和SurfaceView一起工作时,这必须被同一运行的SurfaceView的窗口线程来调用
参数
format PixelFormat的常量.
参见 PixelFormat
public abstract void setKeepScreenOn (boolean screenOn)
当surface被显示的时候是否启用或禁用屏幕保持打开状态,默认是禁用,允许屏幕关闭,启用选项有效时,可以安全的调用任何线程。
参数
screenOn 为ture时强制屏幕保持打开状态,fasle允许气关闭
public abstract void setSizeFromLayout ()
允许suface基于容器的布局来改变大小(这是默认的),当启用此功能,就应该监视surfaceChanged(SurfaceHolder, int, int, int)应对suface的大小变化,当和SurfaceView一起工作时,这必须被同一运行的SurfaceView的窗口线程来调用
扩展:android surfaceholder / surfacechanged / surfaceholder什么意思
surfaceholder SurfaceHolder
public abstract void setType (int type)
设置该surface的类型
参数
type 该surface的内存类型
public abstract void unlockCanvasAndPost (Canvas canvas)
在surface完成编辑像素,该函数调用后,surface的当前像素就会在屏幕上显示,但是它的数据会丢失,尤其是没有保证surface数据保持不变的时候再次调用lockCanvas()。[www.61k.com) 参数
canvas 先前调用lockCanvas()返回的Canvas
参考
lockCanvas()
补充
在用SurfaceView进行游戏开发过程中,用到SurfaceHolder来处理它的Canvas上画的效果和动画是必不可少的。用于控制表面,大小,像素等。其中特别要注意以下的几个函数:
abstract void addCallback(SurfaceHolder.Callback callback);
// 给SurfaceView当前的持有者一个回调对象。
abstract Canvas lockCanvas();
// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作了。
abstract Canvas lockCanvas(Rect dirty);
// 锁定画布的某个区域进行画图等..因为画完图后,会调用下面的unlockCanvasAndPost来改变显示内容。 // 相对部分内存要求比较高的游戏来说,可以不用重画dirty外的其它区域的像素,可以提高速度。
abstract void unlockCanvasAndPost(Canvas canvas);
// 结束锁定画图,并提交改变。
在android中开发游戏,一般来说,或想写一个复杂一点的游戏,是必须用到SurfaceView来开发的。 经过这一阵子对android的学习,我找到了自已在android中游戏开发的误区,不要老想着用Layout和view去实现,不要将某个游戏
中的对象做成一个组件来处理。应该尽量想着在Canvas(画布)中画出游戏戏中的背景、人物、动画等... SurfaceView提供直接访问一个可画图的界面,可以控制在界面顶部的子视图层。SurfaceView是提供给需要直接画像素而不是使用
窗体部件的应用使用的。Android图形系统中一个重要的概念和线索是surface。View及其子类(如TextView, Button)
要画在surface上。每个surface创建一个Canvas对象(但属性时常改变),用来管理view在surface上的绘图操作,如画点画线。
还要注意的是,使用它的时候,一般都是出现在最顶层的
使用的SurfaceView的时候,一般情况下还要对其进行创建,销毁,改变时的情况进行监视,这就要用
surfaceholder SurfaceHolder
到SurfaceHolder.Callback.
例子
SurfaceView1.Java
package com.mxgsa.drawtest.view;
import java.util.Vector;
import com.mxgsa.drawtest.common.Utils;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurfaceView1 extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder sHolder = null;
private Vector<Float> xs = new Vector<Float>();
private Vector<Float> ys = new Vector<Float>();
private boolean isRun = true;
public SurfaceView1(Context context, AttributeSet attribute) {
super(context, attribute);
sHolder = getHolder();
sHolder.addCallback(this);
// TODO Auto-generated constructor stub
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
new Thread(new MyLoop()).start();
surfaceholder SurfaceHolder
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
isRun = false;
Utils.showLog(this.getClass().getName(), "surfaceDestroyed"); }
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);// 这里是绘制背景
Paint p = new Paint(); // 笔触
p.setAntiAlias(true); // 反锯齿
p.setColor(Color.BLACK);
p.setStyle(Style.STROKE);
for (int i = 0; i < xs.size(); i++)
canvas.drawCircle(xs.elementAt(i), ys.elementAt(i), 10, p); }
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() == MotionEvent.ACTION_DOWN) {
xs.add(event.getX());
ys.add(event.getY());
}
return true;
}
class MyLoop implements Runnable {
// 熟悉游戏编程的应该很面熟吧,主循环
public void run() {
Canvas c = null;
// TODO Auto-generated method stub
while (isRun) {
try {
synchronized (sHolder) {
c = sHolder.lockCanvas();
onDraw(c);
Thread.sleep(50);
}
} catch (Exception e) {
surfaceholder SurfaceHolder
} finally {
if (c != null) {
sHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
MainActivity.Java
package com.mxgsa.drawtest;
import com.mxgsa.drawtest.view.SurfaceView1;
扩展:android surfaceholder / surfacechanged / surfaceholder什么意思
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
/** Called when the activity is first created. */ @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(new SurfaceView1(this,null)); }
}
扩展:android surfaceholder / surfacechanged / surfaceholder什么意思
本文标题:surfaceholder-SurfaceHolder.Callback61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1