OpenGLに行く前にSurfaceViewを実装してみた
Android + OpenGL ESをちょっと調べてて、そこに行くよりも前にSurfaceViewを扱ったほうが良さそうなことに気がついた。
SurfaceViewというのは、名前からも分かるとおり、Viewのサブクラスです。以前連載第4回の「簡単でワクワクするAndroidウィジェット10連発!」で紹介した「ウィジェット」も、同様にViewのサブクラスですが、それらのウィジェットとSurfaceViewには決定的な違いがあります。
それは、描画の方式が違うのです。パッケージ「android.widget」に属するウィジェットは、アプリケーションのスレッド内で描画が行われるため、定期的に再描画を繰り返すゲームなどには向いていません。一方、SurfaceViewは、アプリケーションのスレッドと描画処理のスレッドが独立しているため、定期的な再描画に向いています。
例外的に、android.widget.VideoViewクラスは、SurfaceViewのサブクラスです。「SurfaceViewが動画再生などの負荷の描画処理に向いている」という一例ですね。
SurfaceViewならAndroidで高速描画ゲームが作れる (1/3) - @IT
アニメーションのような「動きのあるもの」を実装するにはSurfaceViewを使わないとダメらしい。ちなみにAndroidでOpenGLを叩くViewもGLSurfaceViewというSurfaceViewを継承したクラスになってるので、それだけ重要だということか。
とりあえずSurfaceViewを使って文字列を描画するだけのコードを書いてみた。Viewを継承した場合と比べると、僅かに冗長なコードになる。
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.view.SurfaceHolder; import android.view.SurfaceView; public class HelloActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new MySurfaceView(this)); } private class MySurfaceView extends SurfaceView { public MySurfaceView(Context context) { super(context); getHolder().addCallback(new SurfaceCallback()); } private class SurfaceCallback implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { Canvas canvas = holder.lockCanvas(); // 背景色を白に canvas.drawColor(Color.WHITE); // 文字列を描画 Paint paint = new Paint(); paint.setColor(Color.BLACK); paint.setAntiAlias(true); paint.setTextSize(16); canvas.drawText("hoge", 20.0f, 20.0f, paint); holder.unlockCanvasAndPost(canvas); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } } } }