2014.02.20
AndroidTips | SurfaceViewを使ってみました
SurfaceViewを使ってみました
皆さんにとってAndroidの画面に関する部分というと、ButtonやTextViewといった所謂Viewが馴染みが深いところでしょうか。
ViewはsetContentView()メソッドを用いることにより、画面に追加することができます。
ところで、アニメーション等を使用したい場合、かなり細かいところまで制御する必要が出てきます。
またその場合、描画面を自分で操作することもあります。
そのようなときにSurfaceViewを使用します。
SurfaceViewでは以下の一連の流れで描画を行います。(基本的には)
- ロックとCanvasの取得
- 描画
- アンロックと更新
lockCanvas:画面のサーフェイスをロックし、描画の為のCanvasを返す
描画処理
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()
- surfaceCreated()
- surfaceDestroyed()
- onTouchEvent()
45行目のsurfaceChanged()メソッドは、SurfaceViewの変更時に呼び出されるメソッドです。
引数は下表の通りです。
データ型 | 引数名 | 概要 |
---|---|---|
SurfaceHolder | holder | 変更されたSurfaceViewのSurfaceHolderホルダー |
int | format | 変更されたSurfaceViewのピクセル形式 |
int | width | 変更されたSurfaceViewの横幅 |
int | height | 変更されたSurfaceViewの縦幅 |
52行目のsurfaceChanged()メソッドは、SurfaceViewが最初に生成されたときに呼び出されるメソッドです。
引数は下表の通りです。
データ型 | 引数名 | 概要 |
---|---|---|
SurfaceHolder | holder | SurfaceViewが生成されるSurfaceHolderオブジェクト |
59行目のsurfaceChanged()メソッドは、SurfaceViewが破棄されるときに呼び出されるメソッドです。
引数は下表の通りです。
データ型 | 引数名 | 概要 |
---|---|---|
SurfaceHolder | holder | SurfaceViewが破棄されるSurfaceHolderオブジェクト |
65行目のsurfaceChanged()メソッドは、SurfaceViewにてタッチイベントが検知されたときに呼び出される
データ型 | 引数名 | 概要 |
---|---|---|
MotionEvent | event | 発生したタッチイベント等が格納されているeventオブジェクト |
68行目の条件式の値には、以下の値を指定することができます。
定数名 | 概要 |
---|---|
ACTION_DOWN | タッチ(押下)した場合 |
ACTION_MOVE | タッチしたまま離さずにスライドした場合 |
ACTION_UP | タッチした状態から指を持ち上げた場合 |
ACTION_CANCEL | UPとDOWNの同時発生の場合 |
ACTION_OUTSIDE | ターゲットとなっているUIの範囲外をタッチした場合 |