スレッド処理
Viewを利用した画面などを更新をあまりしないでいいもの、たとえば作成した15パズルや、業務データアプリなどは何かのタイミングで任意に画面などを更新すればいいですよね。しかし画像の移動などを使うゲームやリアルタイムチャットなどは一定の間隔で更新しなければいけません。そのためのSurfaceViewと呼ばれるメソッドが用意されています。それがスレッド処理と呼ばれるものです。わたしのイメージ的にはViewを使った処理では、10個画像があったら1つずつ画像を作成して1つずつ画像を表示していきますが、SurfaceViewでは10個作成して表示を一度の処理でやるイメージでしょうか。
おためしで
SurfaceViewを使ったプログラミングを組むにあたり、もっと効率的なやり方があると思うのですが、その勉強をする前にわたしはがまんができなくなり無理やり使用して作成することにしました。なので今回はSurfaceViewの紹介くらいに思っておいて下さい。
今回作成使用したファイルは3つです。
|
ファイル名「SerfaceViewActivity.java」
package and.roid;
import android.app.Activity;
import android.os.Bundle;
import android.graphics.*;
import android.view.*;
public class SerfaceViewActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(new SurfaceViewView(this));
}
}
|
|
|
ファイル名「SurfaceViewView.java」
package and.roid;
import android.content.Context;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.graphics.*;
import android.view.*;
public class SurfaceViewView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
public static final int BOXKAZU = 10; //ボックスの最大数
public static final int BOXBIG = 100; //ボックスの最大大きさ
public static final int BOXMIN = 10; //ボックスの最小の大きさ
public static final int MAXBOXVXY = 20; //ボックスの最大移動量
public static final int MINBOXVXY = 5; //ボックスの最小移動量
private SurfaceHolder holder;
private Thread thread;
private boolean start=false; //最初の1つのボックスが作成されているかどうか
private int box=0; //作成したボックスの数
private RectBox[] rect = new RectBox[BOXKAZU];
//コンストラクタ
public SurfaceViewView(Context context) {
super(context);
// TODO 自動生成されたコンストラクター・スタブ
holder = getHolder();
holder.addCallback(this);
holder.setFixedSize(getWidth(), getHeight());
}
public void run() {
// TODO 自動生成されたメソッド・スタブ
Canvas canvas;
Paint p = new Paint();
p.setAntiAlias(true);
while(thread != null){
canvas = holder.lockCanvas();
canvas.drawColor(Color.WHITE);
p.setTextSize(30);
p.setColor(Color.BLACK);
if(start==true){
for(int i=0;i<box;i++){
rect[i].DrawBox(canvas, p);
rect[i].move();
}
}
holder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(50);
} catch (Exception e){}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO 自動生成されたメソッド・スタブ
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO 自動生成されたメソッド・スタブ
thread = new Thread(this);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO 自動生成されたメソッド・スタブ
thread = null;
}
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();
int x = (int)event.getX();
int y = (int)event.getY();
switch(action){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
if(box<BOXKAZU && x<getWidth()-BOXBIG && y<getHeight()-BOXBIG){
start=true;
rect[box] = new RectBox();
rect[box].init(x,y,BOXBIG,BOXMIN,MAXBOXVXY,MINBOXVXY,getWidth(), getHeight());
box++;
}
break;
}
return true;
}
}
|
|
|
ファイル名「RectBox.java」
package and.roid;
import java.util.Date;
import java.util.Random;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
public class RectBox {
private int px,py; //ボックの座標
private int vx,vy; //ボックスの移動量
private int col; //カラー
private int bxy; //ボックスの大きさ
private int gw,gh; //画面の大きさ
//コンストラクタ
RectBox(){
super();
}
//初期化
public void init(int x, int y, int b,int m, int maxvxy, int minvxy, int ww, int wh){
Random r = new Random(new Date().getTime());
gw = ww;
gh = wh;
px = x;
py = y;
vx = r.nextInt(maxvxy-minvxy)+minvxy;
if(r.nextInt(100)>50) vx *= -1;
vy = r.nextInt(maxvxy-minvxy)+minvxy;
if(r.nextInt(100)>50) vy *= -1;
col = Color.rgb(r.nextInt(240)+10, r.nextInt(240)+10, r.nextInt(240)+10);
bxy = r.nextInt(b-m)+m;
}
//ボックス表示
public void DrawBox(Canvas c, Paint p){
p.setStyle(Paint.Style.FILL);
p.setColor(col);
c.drawRect(new Rect(px,py,px+bxy,py+bxy), p);
}
//ボックス移動
public void move(){
if(px<0 || gw<px+bxy) vx =- vx;
if(py<0 || gh<py+bxy) vy =- vy;
px += vx;
py += vy;
}
}
|
|
|
|
|
このプログラムの説明
画面をタッチして話すとボックスが生成され移動します。画面端にくると反射してまた移動を繰り返します。
タッチできる範囲は画面右、画面下の範囲からボックスの最大大きさで設定した分をマイナスした範囲(100とすると座標0,0から座標380、754)内がタッチ可能範囲となります。これはその範囲外でタッチした時に、ボックスの大きさが画面外に出てしまうのを避けるためです。
Surfaceメソッドで自動生成されるメソッドがあったりでちょっと長くなっていますが、runメソッドに中に処理を書きtry{}catchでしめる感じでしょうか。
プログラムの流れは、SurfaceViewViewが呼び出された時に、runが呼び出され内容が処理されていくかんじです。
最初はボックスは生成されず、タッチし、離した時に配列設定しているRectBoxクラスが生成されます。
RectBoxが呼び出された時のコンストラクタでボックスの値を初期化してもよかったのですが、初期化処理initと分けました。
初期化はタッチした位置でボックス生成、移動量は設定範囲でランダム。if文でのマイナスの設定は、動き出しの方向を決める設定で、100のうち50より大きければマイナス。というふうに二分の一の確率でマイナスに設定。カラーはRGBのそれぞれを255の中をランダムで設定。すべて0だと白になりそれでは見えないので10以上になるように設定。最後にボックスの大きさも設定されたランダムで設定このクラスには3つのメソッドがあり、初期化、表示、移動の3つだけの簡単なものです。
全然たいしたことをしてませんし、まだまだごちゃごちゃしているのはゆるして下さい(土下座)。
Surfaceメソッドは、もう固定でこういうふうに使うと覚えたほうがいいかもしれませんね。
これで初心者脱出だ!