ラベル デモ の投稿を表示しています。 すべての投稿を表示
ラベル デモ の投稿を表示しています。 すべての投稿を表示

2011年7月22日金曜日

SurfaceViewを試す (SurfaceView Example)

@ITの連載記事 SurfaceViewならAndroidで高速描画ゲームが作れる のサンプルを試しながらSurfaceViewに関して学んでみたり。

途中で気がついたんですが、連載のサンプルはAndroid2.0(API level5)ベースみたいですね。Android1.6(API level4)で試してたので、そのままでは動かないところがありました。

android:theme="@android:style/Theme.Wallpaper"

ってListViewの背景をホーム画面の背景にあわせる設定が利かないとか。仕方ないので適当な画像を用意して設定しました。

listView.setBackgroundResource(R.drawable.rgm79c);


また1.6で抽象クラスだったのが2.0で実装されたのか、@Overrideが軒並みエラーになっていたので削除してみたり。設定の違いかもしれませんが。

この状態でViewを透過させる Transparent SurfaceView などのサンプルは問題なく動作しました。なかなか面白いですね。


また Offscreen はゲームなどに必須のダブルバッファリングに関するサンプルで、非常に参考になりました。ただこのサンプル、

Canvas canvas = holder.lockCanvas();
/* ここに osb の更新処理 */
canvas.drawBitmap(osb, 0, 0, null);
holder.unlockCanvasAndPost(canvas);

ってなっていて、lockCanvas()が名前どおりのロックする関数だったら、ダブルバッファリングの意味が薄い気がw

/* ここに osb の更新処理 */
Canvas canvas = holder.lockCanvas();
canvas.drawBitmap(osb, 0, 0, null);
holder.unlockCanvasAndPost(canvas);

と修正しておきました。これが正しい… ですよね?たぶん…

もっとも解説には「Androidではフレームワークが内部でダブルバッファリングを行ってくれるため、オフスクリーンバッファを持たなくてもよくなりました」とありますので、このへんは気にしなくて良い部分かもしれません。

実際、ちょっと描画を重くしてフレームレートを表示させてみましたが、Offscreen/NoOffscreen サンプル共にあまり違いが感じられませんでした。


解説にもありますが、Offscreen手法はあくまで他の環境用のアプリとロジックなどを共用する場合にのみ使えば良いのかもしれませんね。

で、最後は入力系のイベント処理です。まず、タッチ入力の処理が笑っちゃうほどシンプルなので転載します。

public boolean onTouchEvent(MotionEvent event) {
  left = event.getX();
  top = event.getY();
  doDraw();
  return true;
}
void doDraw() {
  Canvas canvas = getHolder().lockCanvas();
  canvas.drawBitmap(bitmap, left, top, null);
  getHolder().unlockCanvasAndPost(canvas);
}

セットアップなど必要ですが、基本これだけで↓が動くのはなかなかです。


そして定番の、カーソルでオブジェクトを動かす GameSample ですね。自身でRunnableを実装して

public void run() {
  while (true) { doDraw(); }
}

し続けてonKeyイベントの結果を反映させ続けるという、漢気あふれる作りに目を奪われますが、カーソルでロボット君を自在に動かすのは楽しいものです。


とりあえずSurfaceViewに関して、最低限は使えるようになった気がします。

2011年7月18日月曜日

Google Map を表示 (MapsDemo)

最初はSDKにあったMapsDemoサンプルで遊んでみました。地図/位置情報/GPSを使うAndroidアプリを作るには など参考に、MapView Activity に MyLocationOverlayを追加して門前仲町駅のあたりを表示しています。


AVDエミュレーターに位置を指定する方法がわからず苦労しましたが、Eclipseの「ウィンドウ(W)→Viewの表示(V)」から"Emulator Control"ビューを表示させ、その中のLocation Controlsを使って指定できるようです。


Location値を得るにはGoogle Mapで目的の場所を表示した後、以下のBookmarkletを実行すると得られます。

javascript:void(prompt('',gApplication.getMap().getCenter()));

その後、setBuiltInZoomControls(true) で拡大縮小メニューを追加してみたり、お気に入りのお店(焼肉ドラゴン、魚三酒場)の位置を ItemizedOverlay でアイコン表示してみました。


Android2.1+Google APIs の時点では、ItemizedOverlay にはちょいと癖がありますね。抽象クラスなので継承して createItem() size() をoverrideしないといけないんですが、これが謎。

内部的に扱うのは List<OverlayItem> なので、とりあえずはソレ実装しておいてくれれば親切じゃない?とか思います。過保護すぎますかね?

なお事前にデータを用意している場合、継承したクラスのコンストラクタ内などでpopulate(); をコールしないと、初期化が不十分なのかエラーになります。

アイテムごとにアイコンを変えるのは、変更したい OverlayItem に setMarker() でアイコンを指定してあげればOK。これは簡単でした。


ただ「アイコンの横に店の名前を表示する」ことが難しい。OverlayItem のコンストラクタでTitleを指定しているのに、これを実際に表示する設定がわからない。

ググってみたら drawを書き換える力技のページ がヒットするところをみると、現時点では標準的な手段が提供されていない感じですかね?困ったものです。

ただアイコン+表示テキストを動的に生成して、それを個々にアイコンとして指定することで擬似的に実現できそうですね。面倒そうなので、実際に必要になったらチャレンジするとしますw

また ItemizedOverlay に OnTap() という関数をみつけたので、Override してみました。マーカーをタップすることで、その店の詳細情報を表示するダイアログを表示します。なんか、アプリっぽい感じになりましたね~


さて、ちょっと話を変えます。

ソースを眺めてますと、最初のメニュー画面(MapsDemo)もなかなか面白い作りになっていることに気がつきます。


このリストは以下のようなロジックで動的に検索されるよう組まれています。

Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);

PackageManager pm = getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);

アクションがMAINで、カテゴリがSAMPLE_CODEを受け入れるActivityをパッケージ内から動的に検索して追加しています。条件に合う設定のActivityを追加するだけで、既存コードは変更無しでリストに追加できますね。

Android の Intent の仕組みをうまく利用しているサンプルと言えましょう。

同じくMapsDemo Activityなんですが、以下のような事前定義された値を使っていますね。ListView用の最もシンプルな設定(テキストの一覧)の模様。

android.R.layout.simple_list_item_1
android.R.id.text1

APIサイト に詳細が無くて弱っていたのですが、visible trueさんのサイトソースが転載 されていて理解できました。また他の定義値に関して public static void mainサイト の simple_list_item_2とtwo_line_list_itemの表示の違い エントリが参考になりました。

というわけで適当なコメントを追加して simple_list_item_2 に変更してみた結果がこちらw