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