Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中使用SurfaceView和Canvas來繪制動畫

Android中使用SurfaceView和Canvas來繪制動畫

編輯:關於Android編程

其實每個View中都有Canvas可以用來繪制動畫,只需要在這個View中重載onDraw()方法就可以,但是SurfaceView類是一個專門用來制動動畫的類。


Canvas(中文叫做"畫布")就和HTML5中的canvas標簽一樣可以在一定區域內自由繪制圖形。Canvas+SurfaceView制作的動畫與View Animation和Property Animation這類動畫比起來更加適合大量的集中播放的動畫,比如游戲畫面、相機的圖像顯示等。


因為SurfaceView通常會在另一個專門的線程中不斷重繪界面,所以不像其他動畫那樣要在主線程(UI線程)中播放動畫的同時還要消耗一定的流暢度用來響應用戶輸入。


在使用SurfaceView時需要注意下面這些要點:

1)每個SurfaceView都需要一個SurfaceHolder對象來處理這個SurfaceView的生命周期和獲取這個SurfaceView的Canvas對象,可以通過調用SurfaceView的getHolder()方法來獲取它的SurfaceHolder對象。


2)使用SurfaceView時一般是通過繼承SurfaceView的方式來實現,可以順便implements兩個接口,分別是Runnable和SurfaceHolder.Callback。第二個接口需要重載三個函數,這三個函數就是SurfaceView的生命周期處理了,可以通過SurfaceHolder對象的addCallback()方法把實現好的Callback對象傳進去。


3)在使用SurfaceView的Canvas時一定要記得加鎖同步,因為不能讓畫布同時繪制多個圖案,通過調用這個SurfaceView的SurfaceHolder對象的lockCanvas()就可以做到這一點。繪制完畢後在調用SurfaceHolder對象的unlockCanvasAndPost()方法就可以解鎖並更新。


下面給出了一個用SurfaceView和Canvas繪制動畫的例子,一般直接復制上就可以運行看到效果:

package com.example.canvastest;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

public class MainActivity extends Activity {
	/*
	 * 這個類用來當測試的物件,會沿著方形路線持續移動
	 */
	class GameObject {
		private float x;
		private float y;
		private Bitmap img;
		private Paint paint;

		public GameObject() {
			this.img = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
			this.x = 100;
			this.y = 100;
			this.paint = new Paint();
		}

		// 在SurfaceView加鎖同步後傳給自己的Canvas上繪制自己
		public void drawSelf(Canvas canvas) {
			canvas.drawBitmap(img, x, y, paint);
		}

		// 獲取物件下一次要繪制的位置(這裡是沿著一個邊長為400的正方形不斷運動的)
		public void getNextPos() {
			if (y == 100 && x != 500)
				x += 5;
			else if (x == 500 && y != 500)
				y += 5;
			else if (y == 500 && x != 100)
				x -= 5;
			else if (x == 100 && y != 100)
				y -= 5;
		}
	}

	/*
	 * 這個類就是加工了SurfaceView之後的類,所有要運動的物件都最終放在這裡進行繪制
	 */
	class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
		private Thread thread; // SurfaceView通常需要自己單獨的線程來播放動畫
		private Canvas canvas;
		private SurfaceHolder surfaceHolder;

		private GameObject obj;

		public MySurfaceView(Context c) {
			super(c);
			this.surfaceHolder = this.getHolder();
			this.surfaceHolder.addCallback(this);
			this.obj = new GameObject();
		}

		@Override
		public void run() {
			while (true) {
				obj.getNextPos();
				canvas = this.surfaceHolder.lockCanvas(); // 通過lockCanvas加鎖並得到該SurfaceView的畫布
				canvas.drawColor(Color.BLACK);
				obj.drawSelf(canvas); // 把SurfaceView的畫布傳給物件,物件會用這個畫布將自己繪制到上面的某個位置
				this.surfaceHolder.unlockCanvasAndPost(canvas); // 釋放鎖並提交畫布進行重繪
				try {
					Thread.sleep(10); // 這個就相當於幀頻了,數值越小畫面就越流暢
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder arg0) {
			Toast.makeText(getApplicationContext(), "SurfaceView已經銷毀", Toast.LENGTH_LONG).show();
		}

		@Override
		public void surfaceCreated(SurfaceHolder arg0) {
			Toast.makeText(getApplicationContext(), "SurfaceView已經創建", Toast.LENGTH_LONG).show();
			this.thread = new Thread(this);
			this.thread.start();
		}

		@Override
		public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
			// 這裡是SurfaceView發生變化的時候觸發的部分
		}
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(new MySurfaceView(getApplicationContext())); // 別忘了開始的時候載入我們加工好的的SurfaceView
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
}


如果轉載請注明出處:http://blog.csdn.net/gophers



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved