libro
www.tuyano.com
Google androidプログラミング入門

SurfaceViewによる高速描画 (4/5)

作成:2010-10-31 13:20
更新:2010-10-31 13:20

■MySurfaceViewクラスのソースコード

では、「MySurfaceView」クラスを作成しましょう。コード欄に簡単なサンプルコードを掲載しておきます。

これは、画面にSurfaceViewを表示し、白い背景上に赤い円を描くサンプルです。画面をタッチすると、タッチした場所に円が移動します。起動時には画面の中心にえんが表示されるはずです。

ここでは、コンストラクタから「init」メソッドを呼び出し、ここで初期化処理を行っています。初期化処理では、まずSurfaceHolderインスタンスを取得し、それにSurfaceHolder.Callbackのコールバックを設定する、という処理をしています。
holder = getHolder();
holder.addCallback(this);
SurfaceViewの「getHolder」でSurfaceHolderは取得できます。そして取得したSurfaceHolderの「addCallback」を呼び出して、コールバックに設定するインスタンスを指定します。これにより、サーフェイス上で何かの処理が行われると、コールバックに設定されたインスタンス内のメソッドが呼び出されるようになります。
setFocusable(true);
requestFocus();

その後にある2文は、フォーカスに関する処理です。「serFocusable」は、フォーカス可能にするためのものです。また「requestFocus」は、実際にビューにフォーカスを設定するためのものです。

なお、フォーカスに関しては、この他にタッチモードでのフォーカスを可能にする「setFocusableInTouchMode」というメソッドもあります。これは特に指定しなくとも、普通にonTouchEventでタッチの処理をするのには問題ないようです。(setFocusableした段階でデフォルトでtrueに設定されているのかも知れません)

描画の処理は「draw」というメソッドを定義して、ここで行っています。このメソッドは、surfaceCreated(サーフェイスが生成されたとき)と、onTouchEventMotionEvent.ACTION_DOWN時(タッチしたとき)に呼び出すようにしてあります。このdrawでの処理を整理すると、以下のようになることがわかるでしょう。
Canvas c = holder.lockCanvas();
……Canvasを使って描画をする……
holder.unlockCanvasAndPost(c);
SurfaceViewでは、通常のViewonDrawのように、引数でCanvasが渡されるわけではありません。ですから、最初にCanvasを取得するところから始めます。「lockCanvas」は、サーフェイスの表示をロックし、描画のためのCanvasを返します。そして「unlockCanvasAndPost」は画面のロックを解除して表示を更新します。SurfaceViewでは、このように「ロック→Canvas取得→描画→アンロック&更新」という一連の流れが描画の基本となるのです。

実際の描画処理は、通常のViewと何ら変わるところはありません。drawをそれぞれで修正して、動作を確認してみれば、SurfaceViewの基本はすぐに飲み込めるでしょう。

※プログラムリストが表示されない場合

AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。

●プログラム・リスト●

package jp.tuyano.sample;

import android.content.Context;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.*;

public class MySurfaceView extends SurfaceView implements
		SurfaceHolder.Callback {

	private SurfaceHolder holder;
	private float x, y;

	public MySurfaceView(Context context) {
		super(context);
		init();
	}

	public MySurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public MySurfaceView(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public void init() {
		holder = getHolder();
		holder.addCallback(this);
		setFocusable(true);
		requestFocus();
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder,
			int format, int width, int height) {}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		x = getWidth() / 2;
		y = getHeight() / 2;
		draw();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			x = event.getX();
			y = event.getY();
			draw();
		}
		return super.onTouchEvent(event);
	}

	public void draw() {
		Canvas c = holder.lockCanvas();
		c.drawColor(Color.WHITE);
		Paint p = new Paint();
		p.setStyle(Style.FILL);
		p.setColor(Color.RED);
		c.drawCircle(x, y, 50, p);
		holder.unlockCanvasAndPost(c);
	}
}

※関連コンテンツ

「Google androidプログラミング入門」に戻る