
SurfaceView是View的继承结构中一个比较特殊的子类,它的作用是提供一个第二线程来完成图形的绘制。因此应用程序不需要等待View的图形绘制,第二线程会异步完成图形的绘制。
SurfaceView实现的步骤:
继续SurfaceView并实现SurfaceHolderCallback接口,该接口提供了SurfaceView创建、属性发生变化、销毁的时间点,那么你可以在适当的时间点完成具体的工作。
在SurfaceView初始化的时候调用SurfaceViewgetHolder()方法获取一个SurfaceHolder,SurfaceHolder用于管理SurfaceView的工作过程。为了让SurfaceHolder起作用,必须为SurfaceHolder添加回调方法(即第一步实现的SurfaceHolderCallback):
[java] view plaincopyprint
SurfaceHolderaddCallBack(SurfaceHolderCallback);
在SurfaceView内创建第二线程的内部类(暂命名为SecondThread),它的主要任务是完成Canvas的图形绘制。为了能让SecondThread获得Canvas实例,必须给SecondThread传递在步骤二中获得的SurfaceHolder。现在就可以通过SurfaceHolderlockCanvas()方法得到Canvas实例,并在Canvas上绘制图形。当图形绘制完成后,必须马上调用SurfaceHolderunlockCanvasAndPost()为Canvas解锁,使其他线程可以使用该画布。
有几个注意点:
每一次通过SurfaceHolder获取的Canvas都会保持上一次绘制的状态。如果需要重新绘制图形,可以通过调用CanvasdrawColor()或CanvasdrawBitmap()来擦除上次遗留的图形。
并不一定只用第二线程来绘制图形,也可以开启第三,第四个线程来绘制图形。
注意线程安全。
不需要像View一样,调用invalidate()方法来指示图形的刷新。
SurfaceView的一个范例:
[java] view plaincopyprint
package comsin90lzcandroidsample;
import javautilArrayList;
import javautilCollections;
import javautilList;
import androidcontentContext;
import androidgraphicsCanvas;
import androidgraphicsColor;
import androidgraphicsPaint;
import androidutilAttributeSet;
import androidutilLog;
import androidviewKeyEvent;
import androidviewSurfaceHolder;
import androidviewSurfaceView;
public class CanvasView extends SurfaceView implements SurfaceHolderCallback {
public static class Point {
private float x;
private float y;
public Point(float x, float y) {
thisx = x;
thisy = y;
}
public float getX() {
return x;
}
public void setX(float x) {
thisx = x;
}
public float getY() {
return y;
}
public void setY(float y) {
thisy = y;
}
public Point nextPoint(Orien o) {
float tempX = x;
float tempY = y;
switch (o) {
case UP:
tempY = y - LINE_LENGTH;
break;
case DOWN:
tempY = y + LINE_LENGTH;
break;
case LEFT:
tempX = x - LINE_LENGTH;
break;
case RIGHT:
tempX = x + LINE_LENGTH;
break;
case UNKNOWN:
break;
}
return new Point(tempX, tempY);
}
}
enum Orien {
UP, LEFT, DOWN, RIGHT, UNKNOWN
}
public static class DrawThread extends Thread {
private List<Point> points = Collections
synchronizedList(new ArrayList<Point>());
private boolean mRun;
private Paint mPaint;
private Orien curOrien;
public synchronized void setRun(boolean run) {
thismRun = run;
notifyAll();
}
public synchronized boolean getRun() {
while (!mRun) {
try {
wait();
} catch (InterruptedException e) {
eprintStackTrace();
}
}
return mRun;
}
//当按上下左右键时,生成相应的点坐标
private synchronized boolean doKeyDown(int KeyCode, KeyEvent event) {
synchronized (holder) {
Point p = null;
switch (KeyCode) {
case KeyEventKEYCODE_DPAD_UP:
if (curOrien != OrienDOWN) {
curOrien = OrienUP;
p = curPointnextPoint(curOrien);
}
break;
case KeyEventKEYCODE_DPAD_DOWN:
if (curOrien != OrienUP) {
curOrien = OrienDOWN;
p = curPointnextPoint(curOrien);
}
break;
case KeyEventKEYCODE_DPAD_LEFT:
if (curOrien != OrienRIGHT) {
curOrien = OrienLEFT;
p = curPointnextPoint(curOrien);
}
break;
case KeyEventKEYCODE_DPAD_RIGHT:
if (curOrien != OrienLEFT) {
curOrien = OrienRIGHT;
p = curPointnextPoint(curOrien);
}
break;
default:
curOrien = OrienUNKNOWN;
}
if (p != null) {
curPoint = p;
pointsadd(p);
setRun(true);
}
Logi(LOG_TAG, curOrientoString());
}
return true;
}
//当释放按键时,停止绘图
private synchronized boolean doKeyUp(int KeyCode, KeyEvent event) {
synchronized (holder) {
setRun(false);
curOrien = OrienUNKNOWN;
}
return true;
}
SurfaceHolder holder;
private Point curPoint;
public DrawThread(SurfaceHolder holder) {
thisholder = holder;
mPaint = new Paint();
mPaintsetColor(ColorGREEN);
curPoint = new Point(50, 50);
pointsadd(curPoint);
}
public void resetPoint() {
}
private void doDraw(Canvas canvas) {
for (int i = 0; i + 1 < pointssize(); i += 1) {
Point lp = pointsget(i);
Point np = pointsget(i + 1);
canvasdrawLine(lpgetX(), lpgetY(), npgetX(), npgetY(),
mPaint);
}
}
@Override
public void run() {
Canvas canvas = null;
while (getRun()) {
try {
canvas = holderlockCanvas();
synchronized (holder) {
doDraw(canvas);
}
} finally {
holderunlockCanvasAndPost(canvas);
setRun(false);
}
}
}
}
private DrawThread thread;
public static final String LOG_TAG = "CanvasView";
private static final int LINE_LENGTH = 30;
public CanvasView(Context context) {
super(context);
}
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
//SurfaceView由SurfaceHolder管理
SurfaceHolder holder = getHolder();
holderaddCallback(this);
thread = new DrawThread(holder);
threadstart();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return threaddoKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
return threaddoKeyUp(keyCode, event);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Logi(LOG_TAG, "surfaceChanged");
threadresetPoint();
threadsetRun(true);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Logi(LOG_TAG, "surfaceCreated");
threadresetPoint();
threadsetRun(true);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Logi(LOG_TAG, "surfaceDestroyed");
threadsetRun(false);
}
}
:应该是切到其他界面时surfaceview就执行了onSurfaceDestory方法 但是你的线程还在调用surfaceview里的东西,所以出错了。最好把surfaceView的代码也贴出来
以上就是关于如何使用surfaceview全部的内容,包括:如何使用surfaceview、android surfaceview怎么留住最后一帧、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)