Tips

AndroidTips | SurfaceViewを使ってみました

SurfaceViewを使ってみました

皆さんにとってAndroidの画面に関する部分というと、ButtonやTextViewといった所謂Viewが馴染みが深いところでしょうか。
ViewはsetContentView()メソッドを用いることにより、画面に追加することができます。
ところで、アニメーション等を使用したい場合、かなり細かいところまで制御する必要が出てきます。
またその場合、描画面を自分で操作することもあります。
そのようなときにSurfaceViewを使用します。

SurfaceViewでは以下の一連の流れで描画を行います。(基本的には)

  1. ロックとCanvasの取得
  2. lockCanvas:画面のサーフェイスをロックし、描画の為のCanvasを返す

  3. 描画
  4. 描画処理

  5. アンロックと更新
  6. unlockCanvasAndPost:画面のロックを解除し、表示を更新

サンプルプログラム

package com.example.surfaceviewsample;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainActivity extends Activity {
	private static final String TAG = "SurfaceViewSample";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		MainView view = new MainView(this);
		setContentView(view);
	}

	// SurfaceViewクラスを継承したクラスを作成
	class MainView extends SurfaceView implements SurfaceHolder.Callback {

		private SurfaceHolder holder = null;
		private int[] color = { Color.YELLOW, Color.BLUE, Color.RED,
				Color.GREEN };
		private int idx = 0;

		// MainViewクラスのコンストラクタ
		public MainView(Context context) {
			super(context);

			// getHolder()メソッドを用いてSurfaceHolderオブジェクトを取得
			holder = getHolder();
			// addCallback()を用いて、SurfaceHolder.Callbackオブジェクトをリスナー登録する
			holder.addCallback(this);
		}

		// SurfaceViewのサイズなどが変更されたときに呼び出されるメソッド
		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			Log.e(TAG, "surfaceChanged()");
		}

		// SurfaceViewが最初に生成されたときに呼び出されるメソッド
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			Log.e(TAG, "surfaceCreated()");
			draw();
		}

		// SurfaceViewが破棄されるときに呼び出されるメソッド
		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			Log.e(TAG, "surfaceDestroyed()");
		}

		// SurfaceViewにてタッチイベントが検知されたときに呼び出される
		@Override
		public boolean onTouchEvent(MotionEvent event) {
			Log.e(TAG, event.toString());

			// getAction()メソッドを用いて、eventよりタッチイベントのアクションを取得
			if (event.getAction() == MotionEvent.ACTION_UP) {
				draw();
			}
			return true;
		}

		// 描画
		private void draw() {

			// lockCanvas()メソッドを使用して、描画するためのCanvasオブジェクトを取得する
			Canvas canvas = holder.lockCanvas();

			// 画面全体を一色で塗りつぶすdrawColor()メソッドを用いて画面全体を白に指定
			canvas.drawColor(Color.WHITE);

			// Paintクラスをインスタンス化
			Paint paint = new Paint();

			// カラーを指定
			paint.setColor(color[idx]);

			// Canvas.drawRect()を呼び出すと、正方形や長方形を描画することが可能になる
			// (left:左辺,top:上辺,right:右辺,bottom:下辺,Paintインスタンス)
			canvas.drawRect(50, 100, 200, 300, paint);

			// Canvasオブジェクトへの描画完了したら、unlockCanvasAndPost()メソッドを呼び出し、引数にはCanvasオブジェクトを指定する
			holder.unlockCanvasAndPost(canvas);

			// 三項演算子( 条件式 ? 式1 : 式2)
			// ?の前までがif文の条件式
			// ?の前の値がtrue→:の前の値が返される
			// ?の前の値がfalse:の後の値が返される
			idx = (idx == color.length - 1) ? 0 : idx + 1;
		}
	}
}

追記事項

記事内で使っているメソッドと引数は以下の通りです。

  • surfaceChanged()
  • 45行目のsurfaceChanged()メソッドは、SurfaceViewの変更時に呼び出されるメソッドです。
    引数は下表の通りです。

    データ型 引数名 概要
    SurfaceHolder holder 変更されたSurfaceViewのSurfaceHolderホルダー
    int format 変更されたSurfaceViewのピクセル形式
    int width 変更されたSurfaceViewの横幅
    int height 変更されたSurfaceViewの縦幅


  • surfaceCreated()
  • 52行目のsurfaceChanged()メソッドは、SurfaceViewが最初に生成されたときに呼び出されるメソッドです。
    引数は下表の通りです。

    データ型 引数名 概要
    SurfaceHolder holder SurfaceViewが生成されるSurfaceHolderオブジェクト


  • surfaceDestroyed()
  • 59行目のsurfaceChanged()メソッドは、SurfaceViewが破棄されるときに呼び出されるメソッドです。
    引数は下表の通りです。

    データ型 引数名 概要
    SurfaceHolder holder SurfaceViewが破棄されるSurfaceHolderオブジェクト


  • onTouchEvent()
  • 65行目のsurfaceChanged()メソッドは、SurfaceViewにてタッチイベントが検知されたときに呼び出される

    データ型 引数名 概要
    MotionEvent event 発生したタッチイベント等が格納されているeventオブジェクト


68行目の条件式の値には、以下の値を指定することができます。

定数名 概要
ACTION_DOWN タッチ(押下)した場合
ACTION_MOVE タッチしたまま離さずにスライドした場合
ACTION_UP タッチした状態から指を持ち上げた場合
ACTION_CANCEL UPとDOWNの同時発生の場合
ACTION_OUTSIDE ターゲットとなっているUIの範囲外をタッチした場合


Androidアプリ開発の必須知識!JAVAプログラミングを学べる連載リンク

はじめてのJAVA 連載

Recent News

Recent Tips

Tag Search