カテゴリー別アーカイブ: Android

Android で XML ファイルから Menu を作成する


Android の Menu キーを押した時の Menu の作成、表示方法にはいくつか方法があります。とりあえず静的(内容の変更がない)な場合はあらかじめ XML ファイルに内容を記述して呼び出す形がシンプルで管理もしやすいと思います。

公式サイトでは以下が参考になります。
User Interface > Menus

今回は以下のようなものを用意してみました。Eclipse の “Package Explorer” を右クリックして New -> Android XML File を選択します。 “New Android XML File” ダイアログの “Resource Type” から Menu を選択して “Project” にこの XML ファイルを追加するプロジェクトを選択します。 “File” にはこの XML ファイルの名前を適当に入力します。

最低限、以下のように設定しておけば表示と項目選択時の動作をさせることが出来ます。項目自体の ID は “@+id/toggle_culling” などとして保存することで、 “R.java” ファイルに自動的に ID が追加されます。この ID は後で項目選択時の動作を書く時に使います。メニューボタンに表示させる文字列は “string.xml” に文字列を記入しておき、そこに登録した ID で文字列を引くようにしています。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/toggle_culling"
          android:title="@string/toggle_culling" />
    <item android:id="@+id/toggle_transparent"
          android:title="@string/toggle_transparent" />
    <item android:id="@+id/toggle_texture"
          android:title="@string/toggle_texture" />
    <item android:id="@+id/select_bg_color"
          android:title="@string/select_bg_color" />
</menu>

“string.xml” の例は以下のようになります。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="toggle_culling">カリング</string>
    <string name="toggle_transparent">透明</string>
    <string name="toggle_texture">テクスチャ</string>
    <string name="select_bg_color">背景色</string>
</resources>

メニューボタンが押された時は Activity::onCreateOptionsMenu() が呼び出されるので、これをオーバーライドして MenuInflater::inflate() に先ほど作ったメニューの ID を指定します。

メニューの項目が選択された場合は Activity::onOptionsItemSelected() が呼び出されるので、これもオーバーライドして選択された時の動作を記述します。どれが選択されたかは MenuItem::getItemId() を使って判定をします。この ID は先ほどメニューの XML で “@+id/toggle_culling” などとした ID を使うことが出来ます。Eclipse の補完候補に出てこない場合は XML ファイルの保存を忘れているか、記述ミスがあると思うのでコンソールを確認してみて下さい。

 public boolean onCreateOptionsMenu(Menu menu) {
	  super.onCreateOptionsMenu(menu);
	  MenuInflater inflater = getMenuInflater();
	  inflater.inflate(R.menu.main_menu, menu);
	  return true;
 }
 
 public boolean onOptionsItemSelected(MenuItem item) {
	  switch (item.getItemId()) {
	  case R.id.toggle_culling:
		   m_renderer.toggleCulling();
		   return true;
	  case R.id.toggle_texture:
		   m_renderer.toggleTexture();
		   return true;
	  case R.id.toggle_transparent:
		   m_renderer.toggleTransparent();
		   return true;
	  case R.id.select_bg_color:
		   m_colorPickerDialog.show();
		   return true;
	  default:
		   return super.onOptionsItemSelected(item);
	  }
 }

これらの実行例を以下に示します。これらは直接プログラムに書くことも出来るのですが、XML ファイルなどでプログラムの外に出した方がメンテナンスもやりやすいですし、多言語化にも対応しやすいのでオススメです。

それにしても、Android アプリケーションの開発は Eclipse のプラグインがないとやりにくいですね。私は Emacs 使いなのであまり開発環境は使わないのですが、Android アプリの場合は補完の関係もあり Eclipse 内でプログラミングをすることも時々あります。

Android でマルチタッチを取得する


Android で 3D モデルビューワを作成しているのですが、モデルの拡大操作のためにマルチタッチを使うことにしました。

今まで使っていそうで使っていなかったのですが、それほど苦労することなく実装することが出来ました。
MotionEvent::getPointerCount() でポインタの数(触れられている箇所数)を取得することが出来ます。今回は指一本であれば回転処理、それ以外(指二本)であれば拡大縮小処理ということにしました。

MotionEvent::getPointerId() を使ってそれぞれのポインタ ID を取得します。今回は指二本が前提なので、渡すインデックスは 0, 1 になります。

次に取得した ID を引数にして MotionEvent::findPointerIndex() を呼び出してポインタインデックスを取得します。ポインタインデックスが取得できたらそれを使って、MotionEvent::getX() などを使ってポインタ(指)の位置を取得することが出来ます。

以下が、コードになります。

public boolean onTouchEvent(MotionEvent e) {
     if( e.getPointerCount() == 1 ) {
          // 指一本の場合は回転処理をする
          float x = e.getX();
          float y = e.getY();
 
          switch ( e.getAction() ) {
          case MotionEvent.ACTION_MOVE:
               float dx = x - m_previousX;
               float dy = y - m_previousY;
 
               if ( y > ( m_height / 2 ) ) {
                    dx = dx * -1 ;
               }
 
               if ( x < ( m_width / 2 ) ) {
                    dy = dy * -1 ;
               }
 
               m_angleX -= ( dx ) * 180.0f / 320;
               m_angleY += ( dy ) * 180.0f / 320;
          }
 
          m_previousX = x;
          m_previousY = y;
     }
     else {
          // 指二本の場合は拡大処理をする
          // それぞれの位置を取得する
          int pointer_id_1 = e.getPointerId( 0 );
          int pointer_id_2 = e.getPointerId( 1 );
 
          int pointer_index_1 = e.findPointerIndex( pointer_id_1 );
          int pointer_index_2 = e.findPointerIndex( pointer_id_2 );
 
          float x = e.getX(pointer_index_2) - e.getX(pointer_index_1);
          float y = e.getY(pointer_index_2) - e.getY(pointer_index_1);
 
          // ポインタ間の距離を求める
          float distance = (float) Math.sqrt(x * x + y * y);
 
          switch ( e.getAction() ) {
          case MotionEvent.ACTION_MOVE:
              if( m_previousDistance > distance ) {
                   // 以前の方が距離が離れていた場合は縮小する
                   m_scale -= 0.05f;
              }
              else {
                   // 以前の方が距離が近い場合は拡大する
                   m_scale += 0.05f;
              }
          }
 
          m_previousDistance = distance;
     }
 
     return true;
}

マルチタッチは Android 2.0 以降のみ対応ですが、すでにほとんどの端末が 2.0 以降でしょうからあまり問題なさそうです。
それにしても、すでに Android 4.0 搭載端末も出ているんですよね。月日の経つのは早いものです。

Androidマップの使い方


Androidではクラスライブラリを通じてGoogleマップなどのGoogleのサービスを手軽に使えるようになっています.AndroidでのGoogleマップはAndroidマップというようなので,ここでもそれにならいます.

具体的な使用方法は本などのいろいろな情報源があるのでそちらにゆずるとして,ここでは注意点などを簡単にまとめます.

まずはAPIを利用する際に必要なAPIKeyを取得する必要があるのですが,開発中は開発用のMD5から作成したAPIKeyを利用する必要があります.アプリケーション配布用のMD5では動かないので注意して下さい.APIKeyを間違えた場合は下図のように地図が表示されないようになります.

その他、実装に必要な事項を以下にまとめます.

  • MapActivityを継承する
  • MapViewを適用する

AndroidManifest.xmlの適当な場所にそれぞれを追加

<uses-library android:name="com.google.android.maps" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

レイアウトXMLファイルに以下を追加

<com.google.android.maps.MapView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:apiKey="開発用APIKey"
android:clickable="true"/>

私は開発用のAPIKeyを使うというところに気付かずにはまりましたが,それ意外は特に難しいことなく利用することが出来ました.せっかく手軽に使えるのでこれを利用した面白いアプリケーションを作ってみたいですね.