1. 介绍
对于游戏等对界面要求较高的程序,一般需要控制View中的具体图像显示(如动画功能)下面介绍实现此功能常用的SurfaceView控制。
1) 常用的绘制图像的方法
a) View的invalidate()
直接调用onDraw()绘图
b) View的postInvalidate()
通过消息调用onDraw()绘图
c) SurfaceView
画布的重绘是由一个单独的线程处理,所以不会阻塞,专门为游戏而实现的。
2) SurfaceView
a) 说明
i. 它支持OpenGL ES,2D和3D效果都能实现
ii. 在游戏线程中画图(而非主线程):冻结画布->在画布上绘图->解冻画布->次画布内容绘制到屏幕上
iii. 采用双缓存,避免屏幕闪烁
b) 实现
i. 需要实现Callback接口,它可以用来监听SurfaceView的状态,而从开启和销毁游戏主线程
ii. 需要实现Runnable接口, 它实现了游戏绘图线程
3) 常见问题
a) 双缓存问题
i. 原理:由于内存中存在着两个绘图区,每绘一次,显示其中一个绘图区(交替出现)
ii. 问题:容易出现以下问题:有时只清除了其中一个绘图区,造成了画面叠加。只绘制了部分图像,与之前部分出现叠加。
iii. 解决方法::每次清屏后再画(canvas.drawColor(Color.BLACK))
2. 例程
1) 功能
使用SurfaceView的方式在控件中实现动画
2) 关键字
Android, SurfaceView, 动画,游戏
3) 可从此处下载可独立运行的代码
http://download.csdn.net/detail/xieyan0811/4117465
4) 核心代码及说明
package com.demo.game;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.content.Context;
import android.util.AttributeSet;
public class GameView extends SurfaceView implements Callback,Runnable {
private boolean mIsRunning= false;
private Canvas mCanvas =null;
private SurfaceHoldermSurfaceHolder = null;
private Thread mThread =null;
private Paint mPaint =null;
private int mY = 0;
public GameView(Contextcontext, AttributeSet attr) {
super(context,attr);
mPaint = newPaint();
mPaint.setColor(0xffff0000);
mPaint.setStrokeWidth(3);
mPaint.setAntiAlias(true);
mSurfaceHolder =getHolder();
mSurfaceHolder.addCallback(this);
}
public voidsurfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
public voidsurfaceCreated(SurfaceHolder arg0) { //控制动画开始
mIsRunning = true;
mThread = newThread(this);
mThread.start();
}
public voidsurfaceDestroyed(SurfaceHolder arg0) { //控制动画结束
mIsRunning =false;
try {
mThread.join();
} catch (Exceptione) {
e.printStackTrace();
}
}
public void run() { // 绘图线程
while (mIsRunning){
try {
Thread.sleep(40);
} catch(InterruptedException e) {
e.printStackTrace();
}
synchronized(mSurfaceHolder) {
mCanvas= mSurfaceHolder.lockCanvas();
Draw();
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
private void Draw() { // 绘图函数
mCanvas.drawColor(Color.BLACK); // 清空buffer,以避免图像叠加
mCanvas.drawLine(0,mY, 300, mY, mPaint);
mY++;
if (mY > 300)
mY = 0;
}
};
3. 参考
http://www.uml.org.cn/mobiledev/201110205.asp