SurfaceViewは高速に描画を行うための仕組みです。
通常のViewでは処理が間に合わない、ゲームやマルチメディアなど高速処理に向いています。
別スレッドで描画するため、資源の排他処理などマルチスレッドを意識する必要があります。
SurfaceViewの特徴は以下の3点+3メソッドです。
画面(Surface)を描画する専用スレッドを提供する(資源ロックが発生)
Surfaceの描画には、SurfaceHolderというインターフェイスを利用
描画処理はSurfaceHolderのコールバックとして実装する
SurfaceHolder.Callback.surfaceCreated()
SurfaceHolder.Callback.surfaceChanged()
SurfaceHolder.Callback.surfaceDestroyed()
TechBoosterでは一度、カメラの使用方法(1)、(2)で触れています。
その際は、Cameraというハードウェアのマルチメディア処理を主眼に紹介しました。
今回は改めて描画処理をおこなうSurfaceViewについて解説します。
SurfaceViewを用意する
SurfaceViewの実装ではSurfaceHolderをインターフェイスとして使うため、
描画用のコールバックも必要になります。まとめて内部クラスとして用意します。
実装すべきメソッドは4つで、非常に簡単に用意できます。
SurfaceViewのコンストラクタ
SurfaceHolder.Callback.surfaceChanged()
SurfaceHolder.Callback.surfaceDestroyed()
SurfaceHolder.Callback.surfaceDestroyed()
今回のサンプルでは、わかりやすさを優先してActivityとViewを分離しました。
sampleSurfaceView.java (SurfaceView側)
public class sampleSurfaceView extends SurfaceView implements 
SurfaceHolder.Callback{
    //コンストラクタ
    public sampleSurfaceView(Context context) {   ...  }
    //SurfaceView変更時に呼び出される
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
int height) {  ...  }
    //SurfaceView生成時に呼び出される
    public void surfaceCreated(SurfaceHolder holder) {    ...  }
    //SurfaceView破棄時に呼び出される
    public void surfaceDestroyed(SurfaceHolder holder) {  ...  }
}
Activity側ではSurfaceViewのインスタンスを生成します。
surfaceViewActivity.java (Activity側)
public class surfaceViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new sampleSurfaceView(this));
    }
}
画像と文字列を描画する
必要な処理はコールバックの登録と実装です。
SurfaceViewのコンストラクタで登録処理を行います。
private Bitmap mImage;
//コンストラクタ
public sampleSurfaceView(Context context) {
    super(context);
    getHolder().addCallback(this);
    mImage = BitmapFactory.decodeResource(getResources(), 
R.drawable.bakeneko);
}
6行目のgetHolder()メソッドでSurfaceHolderを取得、さらにコールバックを登録しています。
7行目で今回使うBitmapリソースを用意しています。
注釈:SurfaceViewとは直接関係ありませんが、独自拡張したViewをXmlに記述する場合、 
コンストラクタはpublic sampleSurfaceView(Context context)ではなく、
public sampleSurfaceView(Context context, AttributeSet attrs) が呼び出されるので注意してください。
SurfaceViewの描画に必要なSurfaceHolderのコールバック一覧です。
SurfaceHolder.Callback
コールバック名    通知タイミングと役割
surfaceCreated    生成時。初期画面の描画
surfaceChanged    変更時。画面の更新処理
surfaceDestroyed    破棄時。画面の削除、後処理
サンプルでは更新処理が無いため、surfaceCreatedでの描画処理のみ実装しています。 
//SurfaceView生成時に呼び出される
public void surfaceCreated(SurfaceHolder holder) {
    //初期描画(生成タイミングで描画する必要があるもの)
    //Canvasの取得(マルチスレッド環境対応のためLock)
    Canvas canvas = holder.lockCanvas();
    Paint paint = new Paint();
    paint.setTextSize(24);
    paint.setColor(Color.WHITE);
    //描画処理(Lock中なのでなるべく早く)
    canvas.drawBitmap(mImage, 0, 0, paint);
    canvas.drawText("TechBooster",0,200,paint);
    //LockしたCanvasを解放、ほかの描画処理スレッドがあればそちらに。
    holder.unlockCanvasAndPost(canvas);
}
//SurfaceView変更時に呼び出される
public void surfaceChanged(SurfaceHolder holder, int format, int width, int 
height) {
}
//SurfaceView破棄時に呼び出される
public void surfaceDestroyed(SurfaceHolder holder) {
}
7行目と17行目でCanvasの排他処理を行っています。マルチスレッド環境では資源の競合を考慮して取得時にLock、利用が終了すればunlockして解放する必要があります。
それぞれ、SurfaceHolderのlockCanvas()、unlockCanvasAndPost()を利用します。
 
0 件のコメント:
コメントを投稿