前回のViewクラスを以下のように書き換えてみました。


public class ViewSample extends View
{

private Bitmap bmp = BitmapFactory.decodeResource(super.getResources(), R.drawable.ic_launcher);
private float left = 0;
private float top = 0;

public ViewSample(Context context){

super(context);
}

@Override
public void onDraw(Canvas canvas){

Paint paint = new Paint();
int maxLeft = 800 - bmp.getWidth();
int addTopVal = bmp.getHeight();

left += 10;
if (maxLeft < left) {
left = 0;
top += addTopVal;
}

canvas.drawBitmap(bmp, left, top, paint);
invalidate();
}
}


leftとtopをクラス変数化
あとはonDrawの最後にinvalidateを呼ぶようになりました。

invalidateを呼ぶことでViewが動いている間は定期的にonDrawメソッドが呼ばれます。

なので、今回のソースで画像が左から右、上から下に移動するようになっています。

画面サンプル




サンプル見ても動かないから分かりませんね。

とは言えこのくらいのソースで画像を動かす事ができます。

勘のいい人はお気づきかもしれませんが、
ループの感覚は指定できません

もう何回かViewについて触れたら、本気なゲーム作成方法を記載します。(あと一回かもしれませんが未定)






そろそろ画像表示とか動きとかゲーム寄りな事をしたい人が出てくると思うので、
まずは簡単なViewを解説します。

とりあえず、難しい事は考えずに以下のクラスを用意してください

import宣言もEclipseなら自動でmatigainakuいけます。

public class ViewSample extends View
{

private Bitmap bmp = BitmapFactory.decodeResource(super.getResources(), R.drawable.ic_launcher);

public ViewSample(Context context){

super(context);
}

@Override
public void onDraw(Canvas canvas){

Paint paint = new Paint();
float left = 100;
float top = 200;

canvas.drawBitmap(bmp, left, top, paint);
}
}


次にActivity

public class MainActivity extends Activity
{

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new ViewSample(this));
}
}


setContentViewでR.layout.xml名じゃない?!
まあ、先に作ったViewをセットしてます。

先に画面



ドロイド君が出ましたね。

まずは気になるここ
Bitmap bmp = BitmapFactory.decodeResource(super.getResources(), R.drawable.ic_launcher);
コンパイルエラーになるならここだけです。
エラーが出たら「ic_launcher」って名前の画像をdrawable○○に入れて下さい(画像形式はあまり問いません)

要はdrawableなフォルダからRクラスのdrawableに管理されてるidで画像を読み込んでます。

次にここ
@Override
public void onDraw(Canvas canvas){

Paint paint = new Paint();
float left = 100;
float top = 200;

canvas.drawBitmap(bmp, left, top, paint);
}

ここで読み込んだ画像を表示しています。
Paintは画像の時は気にしなくてOKです。

と、言うことで気にするパターン

@Override
public void onDraw(Canvas canvas){

Paint paint = new Paint();
float left = 100;
float top = 200;
paint.setColor(Color.RED);
paint.setTextSize(30);

canvas.drawText("HOGEHOGE", left, top, paint);
}


画面です。


画面見ても分かりにくいですが、縦位置は以下の注意点があります。
・画像は上の位置を指定
・文字は下の位置を指定
を意味します。

分かりやすいサンプル

public void onDraw(Canvas canvas){

Paint paint = new Paint();
float left = 100;
float top = 200;
paint.setColor(Color.RED);
paint.setTextSize(30);

canvas.drawBitmap(bmp, left,top, paint);
canvas.drawText("HOGEHOGE", left, top, paint);
}


次に画像


同じ位置を指定しているのに、重ならないで表示されていますね。

そうゆうことです。







今回はbangaihenn的にOSのメモリ管理について注意点を記載します。

まずはActivityのソースから
   @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_toast);

Button btn = (Button)findViewById(R.id.test);
Button btn2 = (Button)findViewById(R.id.test2);
btn.setOnClickListener(new BtnExecute());
btn2.setOnClickListener(new BtnExecute());
}

ボタンが2つあって、それぞれ同じクラスにイベント登録しています。

次にイベント処理するクラスのソース

public class BtnExecute implements View.OnClickListener
{

private static String test;

public void onClick(View v)
{
if(R.id.test == v.getId()){
test = "Button1";
} else {
if(null == test){
Toast.makeText(v.getContext(), "test is null", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(v.getContext(), test, Toast.LENGTH_LONG).show();
}
}
}
}


ボタン編でちらっと触れた方法です。
引数のViewからgetIdすると、どのボタンが押されたか分かります。
例ではif文で分けてますが、数が多ければswitchでやる事も多いです。

コードの解説ですが、ボタン1が押されたらstaticな変数testに値をセットします。
ボタン2が押されたらstaticな変数testのnullチェックをして、
nullなら「test is null」と表示
nullじゃなければ変数に入ってる値を表示します。

では動作イメージです。
先にボタン2を押下



次にボタン1を押下後すぐにボタン2を押下



時間をおいてボタン2を押下



nullになってる!Σ( ̄□ ̄;
*ホームボタンでバックグラウンドにして他のアプリを動かしたりしてください
(再現性は端末性能によります。)

ホームボタン押すからだろ!!って人のために
ボタン1→ボタン2→ホームボタン→すぐにボタン2



これが現実です。

onPauseでバックグラウンドになる時にメモリ解放
onRestartで再開時に再生成な作りが良いです。

staticでもfinalなら解放されないとの噂もありますが、
解放される前提でお行儀よく作りましょう。
(androidの開発で謎なヌルポが出たら、これが理由かも)