以前購入したAndroidプログラミングの本を参考に
SurfaceViewをいじってみたんだけど、Android4.xでは
動いたけど、5~6辺りで全くうんともすんとも言わなかったので
色々調べてみたんだけど、なかなかうまく動くモノが無かった。
四苦八苦しながらやっと、サンプルにできるくらいは
出来たので記録。
(一部のAndroid6.0エミュレータではスワイプしたら落ちたけど
原因不明。試しに他の6.0で試してみたら落ちなかったので
Android6.0で落ちると言うことではなさそう。)
SurfaceViewとThread(ここではDrawThread)を
分けているサンプルなどもあるけど
分けて記述することも可能かと思いますが、
ここではSurfaceViewのファイルと一つにまとめて記述しています。
(AndroidStudio 3.1.4で作成)
必要javaファイルは2つ
*MainActivity.java
*SurfaceViewSample.java
■[MainActivity.java](任意の名称に変更して下さい)
(import部分は省略しています)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
public class MainActivity extends AppCompatActivity implements SurfaceViewSample.Callback { //クラス名を変更する場合はこちらも変更して下さい private SurfaceViewSample surfaceViewSample; private void onCreateProcess() { //クラス名を変更する場合はこちらも変更して下さい surfaceViewSample= new SurfaceViewSample(getApplicationContext()); surfaceViewSample.setCallback(this); setContentView(surfaceViewSample); } private void onResumeProcess() { surfaceViewSample.startDrawThread(); } private void onPauseProcess() { surfaceViewSample.stopDrawThread(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); onCreateProcess(); } @Override protected void onResume() { super.onResume(); onResumeProcess(); } @Override protected void onPause() { super.onPause(); onPauseProcess(); } //Callback public void onGameOver() { //CallBack //ゲームオーバーなど表示 // } } |
※コールバックのonGameOver関数はSurfaceViewでゲームオーバーなどの
処理で使用できるように作っているだけで、サンプルでは使用していません。
【setContentView(surfaceViewSample)】の部分を
setContentView(new SurfaceViewSample(getApplicationContext()));
書き方も出来ますが、
Activity側で処理を止めるために(onPauseで止めています)
直接記述はしていません。
また、getApplicationContext()を引数で渡していますが、
thisなどのサンプルも見かけます。
どちらでもいいですが、一応渡すのはContextなので、
getApplicationContextの方がよろすぃみたいな説明を
されている方もいらっしゃいました。
■[SurfaceViewSample.java](任意の名称に変更して下さい)
※gameOver()関数は未使用ですが、ゲームオーバー等の処理で
MainActivityへのコールバックを作成しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Handler; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; public class SurfaceViewSample extends SurfaceView implements SurfaceHolder.Callback { private static final int FPS = 60; DrawThread drawThread; public interface Callback { public void onGameOver(); } private Callback callback; public void setCallback(Callback callback) { this.callback = callback; } private final Handler handler; public SurfaceViewSample(Context context) { super(context); handler = new Handler(); getHolder().addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { startDrawThread(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { stopDrawThread(); } public void processGameAll(Canvas canvas){ int disp_w=canvas.getWidth(); int disp_h=canvas.getHeight(); canvas.drawColor(0xffcccccc);//背景色 } private class DrawThread extends Thread{ boolean isFinished; @Override public void run() { //SurfaceHolder holder = getHolder();//途中でやり方を変更したためコメントアウトw while (!isFinished) { Canvas canvas; //canvas = holder.lockCanvas();//上記コメントアウトの名残w canvas = getHolder().lockCanvas(); if (canvas == null) { stopDrawThread(); }else{ processGameAll(canvas);//メイン描画処理 //holder.unlockCanvasAndPost(canvas);//同じく上記コメントアウトの名残 //getHolder().unlockCanvasAndPost(canvas); } } } } public void startDrawThread() { stopDrawThread(); drawThread = new DrawThread(); drawThread.start(); } public boolean stopDrawThread() { if (drawThread == null) { return false; } drawThread.isFinished = true; drawThread = null; return true; } //ここからMainActivityの関数(UI)へコールバック private void gameOver() { handler.post(new Runnable() { @Override public void run() { callback.onGameOver(); } }); } |
コメントを書く