SurfaceHolder
版本:Android 2.2 r1
结构
继承关系
public interface SurfaceHolder
android.view.SurfaceHolder
概述
抽象接口持有人显示表面。允许您控制面的大小和格式,编辑在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 新的回调接口
public abstract Surface getSurface ()
直接获取Surface对象,这个Surface对象并不总是能获取的。
例如:当使用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
public abstract Canvas lockCanvas (Rect dirty)
和lockCanvas()一样,但允许指定一个脏矩形,再这个矩形的每个像素都必须被绘制,脏矩形外的像素将被保存直到下次调用lockCanvas()。
参数
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的常量.
参见
public abstract void setKeepScreenOn (boolean screenOn)
当surface被显示的时候是否启用或禁用屏幕保持打开状态,默认是禁用,允许屏幕关闭,启用选项有效时,可以安全的调用任何线程。
参数
screenOn 为ture时强制屏幕保持打开状态,fasle允许气关闭
public abstract void setSizeFromLayout ()
允许suface基于容器的布局来改变大小(这是默认的),当启用此功能,就应该监视surfaceChanged(SurfaceHolder, int, int, int)应对suface的大小变化,当和SurfaceView一起工作时,这必须被同一运行的SurfaceView的窗口线程来调用
public abstract void setType (int type)
设置该surface的类型
参数
type 该surface的内存类型
public abstract void unlockCanvasAndPost (Canvas canvas)
在surface完成编辑像素,该函数调用后,surface的当前像素就会在屏幕上显示,但是它的数据会丢失,尤其是没有保证surface数据保持不变的时候再次调用lockCanvas()。
参数
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.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();
}
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) {
} finally {
if (c != null) {
sHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
MainActivity.Java
package com.mxgsa.drawtest;
import com.mxgsa.drawtest.view.SurfaceView1;
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));
}
}
今天的文章SurfaceHolder API分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/33396.html