Android アプリではSurfaceViewというのがあって、
そこで描画処理を行えばいいみたいだ。
しかもCanvasにBitmapをペタペタ貼り付けて、
一気に画面に展開できる。
つまり標準でオフスクリーンを持っているのだ。
だが、ちょっと詰まった。
SurfaceViewを生成したタイミングで
surfaceCreated()が呼ばれるハズなのに呼ばれない。
色々試したがどうにも呼ばれないし
getHolder()の戻り値がnullで先に進めなくなった。
コールバックが上手く設定できていないのか?
ウギギ・・・。
仕方がないので、プロジェクトを再作成して
SurfaceViewを実装してみるとちゃんと動いた。
なんでやねん。
ちゃんと動いたので、スレッドを立てるようにして、
その中で定期的に描画を行うようにした。
自分用にざっくりサンプルを残そう・・・。
ソースコピペ時のインデント直すのメンドイ・・・
◆アクティビティ
public class MainActivity extends Activity {
MySurfaceView mSfV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//画像処理
Paint paint = new Paint();
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dice1);
mSfV = new MySurfaceView(this);
setContentView(mSfV);
mSfV.setOffScreenBmp(bmp);
mSfV.setRefreshFlg(true);
Bitmap bmp3 = Bitmap.createBitmap(480, 320, Bitmap.Config.ARGB_8888);
Bitmap bmp2 = BitmapFactory.decodeResource(getResources(), R.drawable.dice2);
Canvas ofs = new Canvas(bmp3);
ofs.drawBitmap(bmp2, 0, 0, paint);
ofs.drawBitmap(bmp, 100, 50, paint);
mSfV.setOffScreenBmp(bmp3);
mSfV.setRefreshFlg(true);
}
protected void onDestroy() {
super.onDestroy();
// Toast.makeText(this, "onDestory", Toast.LENGTH_SHORT).show();
//スレッドの停止
mSfV.StopThread();
}
}
◆SurfaceView
public class MySurfaceView extends SurfaceView implements Runnable,
SurfaceHolder.Callback {
private Thread thread;
SurfaceHolder holder;
private boolean refreshFlg;
private Bitmap bmp;
public MySurfaceView(Context context) {
super(context);
refreshFlg = false;
holder = getHolder();
getHolder().addCallback(this);
setFocusable(true);
requestFocus();
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
// スレッドの作成と実行(run()の実行)
thread = new Thread(this);
thread.start();
}
// スレッドの削除
public void StopThread() {
thread = null;
}
@Override
public void run() {
// TODO 自動生成されたメソッド・スタブ
// TODO:DEBUG
Log.v("*TEST*", "MySurfaceView_RUN");
long loopCount = 0;
long waitTime = 0;
long startTime = System.currentTimeMillis();
while (thread != null) {
loopCount++;
try {
if (refreshFlg == true) {
draw();
//refreshFlg = false;
}
waitTime = (loopCount * FRAME_TIME)
- System.currentTimeMillis() - startTime;
if (waitTime > 0) {
Thread.sleep(waitTime);
}
} catch (Exception e) {
Log.v("*TEST*", "MySurfaceView_RUN_ERR");
}
}
}
// 描画処理
public void draw() {
Paint paint = new Paint();
Canvas canvas = holder.lockCanvas();
canvas.drawBitmap(bmp, 0, 0, paint);
holder.unlockCanvasAndPost(canvas);
}
//描画フラグ設定
public void setRefreshFlg(boolean flg){
refreshFlg = flg;
return;
}
public Bitmap getOffScreenBmp(){
return bmp;
}
public void setOffScreenBmp(Bitmap bitmap){
bmp = bitmap;
}
}
あかん、インデント直す気になれん・・・。
つーか、括弧の数あってるのか?
やってることは、
アクティビティでSurfaceViewを生成しスレッドを立てる。
これでsurfaceCreatedが呼ばれ、
スレッドが立てられることでrun()が実行される。
run()はスレッドが生きている間、
実際に描画を行うdraw()を日々出し続ける。
後は、アクティビティ側で
描画するビットマップをCanvasに貼りまくり、
定期的にMySurfaceView側のBitmapに渡せばいい。
ソースでは一度画面表示した後、
すぐに別の画像を作成して上書きを行っている。
速すぎて切り替わりを確認することはできないw
アクティビティ終了時にスレッドを削除するようにしている。
これをやらないとアプリ終了後もスレッドが
生き続けて気持ち悪かったので追加した。
放っておいても勝手に停止する・・・らしい?
コメントアウトしているけど、
refreshFlg で全てのアイテムを処理したか
判定して描画を制御する予定。
参考にさせて頂きました!(丸パク・・・)
http://android.keicode.com/basics/surfaceview-1.php
やっと4-3攻略しました!
※コメント投稿者のブログIDはブログ作成者のみに通知されます