SurfaceView在绘制图形方面有什么特点呢,我们都知道,在Android中,图形view交互都是通过主线程来完成的,这样在游戏、应用等多图形交互的时候会发生主线程阻塞,形成卡顿现象。而SurfaceView则是通过另外一个线程来完成的,这样就大大解决了这个问题。下面我们来模拟一下游戏组合图形的移动动画。
值得注意的是:SurfaceView在绘画的时候必须要在SurfaceView创建完成后才能绘画;在绘画的时候需要锁住画板,画完解锁;在绘制移动等动画效果的时候需要将canvas保存,随后进行再restore掉。
源码下载:http://download.csdn.net/detail/liuyu973971883/9598434
效果图:
——————————————————————————————————————————————————————————
首先先创建一个空项目,我们不需要布局文件,只需要在SurfaceView中绘画即可
类文件分为5个文件:
GameView.java用来绘画图形的,继承SurfaceView实现callback接口,此处callback是SurfaceView包下的
Container.java图形view容器,用来存放多个view的
Rect.java绘画矩形view
Circle.java绘画圆形view
MainActivity.java
下面代码和对应解释如下:
MainActivity.java:
package com.oak.learnsurfaceview;
import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class GameView extends SurfaceView implements Callback{
private Contanier contanier;
private Rect rect;
private Circle circle;
private Timer timer;
private TimerTask timerTask;
public GameView(Context context) {
super(context);
//实例化容器
contanier = new Contanier();
//实例化矩形类
rect = new Rect();
//实例化圆形类
circle = new Circle();
//将圆形类加入到rect的容器中
rect.addChildView(circle);
//然后将矩形类加入到整个大的contanier容器中
contanier.addChildView(rect);
//为SufaceView设置回调
getHolder().addCallback(this);
}
//写一个画方法,一定要在SurfaceView创建完毕后才能调用此方法
private void draw(){
//在SurfaceView中画东西一定要先锁住画板
Canvas canvas = getHolder().lockCanvas();
//将画板设置为白色
canvas.drawColor(0xFFFFFFFF);
//将画板传入到容器中
contanier.draw(canvas);
//解锁画板
getHolder().unlockCanvasAndPost(canvas);
}
//开始计时器,用于不断画出组合图形,形成移动效果
public void startTimer(){
timer = new Timer();
timerTask = new TimerTask() {
@Override
public void run() {
draw();
}
};
timer.schedule(timerTask, 10, 10);
}
//暂停计时器,用于在SurfaceView销毁后暂停,如果在SurfaceView销毁后继续画则抛出异常
public void stopTimer(){
if(timer != null){
timer.cancel();
timer = null;
}
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
//SurfaceView创建完毕
@Override
public void surfaceCreated(SurfaceHolder arg0) {
startTimer();
}
//SurfaceView销毁之前调用
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
stopTimer();
}
}
Container.java:
package com.oak.learnsurfaceview;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;
//这个类是一个容器,用于存放View的
public class Contanier {
//设置一个list集合用于存放这个容器
private List<Contanier> list;
private float x = 0;//记住组合图形的x座标
private float y = 0;//记住组合图形的y座标
public Contanier() {
//在这个容器实例化的时候为这个list集合实例化
list = new ArrayList<Contanier>();
}
//对外公开draw方法,调用这个方法即可画出所有View
public void draw(Canvas canvas){
//在移动画板等动画操作,必须先将画板保存,然后释放
canvas.save();
//移动图形
canvas.translate(getX(), getY());
//调用子View复写的childViewDraw方法
childViewDraw(canvas);
//遍历这个集合,从而实现每个View都能够实现画的功能
for (Contanier c : list) {
c.draw(canvas);
}
//释放画板
canvas.restore();
}
//定义这个方法,来供子View重写
public void childViewDraw(Canvas canvas){}
//将View存放的容器存放于list中
public void addChildView(Contanier child){
list.add(child);
}
//移除view容器
public void removeChildView(Contanier child){
list.remove(child);
}
//下面设置x和y的get和set方法
public float getX() {
return x;
}
public float getY() {
return y;
}
public void setX(float x) {
this.x = x;
}
public void setY(float y) {
this.y = y;
}
}
Rect.java:
package com.oak.learnsurfaceview;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
//画一个矩形
public class Rect extends Contanier{
//画笔
private Paint paint;
public Rect() {
//实例化画笔
paint = new Paint();
//将画笔颜色设置为蓝色
paint.setColor(Color.BLUE);
}
//重写Contanier中的childViewDraw方法,画一个100x100的矩形
@Override
public void childViewDraw(Canvas canvas) {
super.childViewDraw(canvas);
canvas.drawRect(0, 0, 100, 100, paint);
//将X和Y座标+1,这里只需要将矩形的x和y座标自增即可,因为圆形是矩形的子View
this.setX(this.getX()+1);
this.setY(this.getY()+1);
}
}
Circle.java:
package com.oak.learnsurfaceview;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
//画一个圆形
public class Circle extends Contanier{
//画笔
private Paint paint;
public Circle() {
//获取画笔实例
paint = new Paint();
//设置画笔为红色
paint.setColor(Color.RED);
}
//重写Contanier中的childViewDraw方法
@Override
public void childViewDraw(Canvas canvas) {
super.childViewDraw(canvas);
//画一个圆位置x:50 y:50,半径为50
canvas.drawCircle(50, 50, 50, paint);
}
}
MainActivity.java:
package com.oak.learnsurfaceview;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//将GameView呈现在主Activity中
setContentView(new GameView(this));
}
}
By:Brycen Liu