アプリケーション内にメニューを作る
Androidのアプリケーションではメニューキーを押すことで、アプリケーション独自のメニューを表示させられます。このメニューは普段は隠れていますが、メニューキーを押したときに画面の下部に表示されます。基本的にはアイコンとテキストから構成されていて、タップすると機能が実行されます。
メニューは、xmlで記述して作ることもできますし、コードからメニューを生成することもできます。今回のサンプルでは、メインアクティビティとアイテム編集アクティビティの2ヵ所でメニューを利用しています。
前者は設定やアイテム追加、アプリケーションの終了などがあり、後者では、設定を保存することなく終了させる取り消し機能とアイテム自体の削除の2つの項目があります。アイテムの削除を編集画面に持ってきたのにはいくつか理由があります。1つは、メイン画面ではアイテムを選択した状態を表すことができないため、どれを削除するのかを指定するのが面倒であること(利用者、コード書く自分両方とも)、簡単に削除できるのもユーザーインターフェースとしてはいいものとは言いがたいので、個々のアイテムの編集画面に移行したのちに削除する仕組みにしました。
メイン画面のメニュー表示は、初期に書いたものであるため、コードで項目を生成させています。これに対して、アイテム編集画面のメニューは、xmlを使って記述してあります。本来なら両方ともxmlにすべきでしょうが、サンプルという性格上、コードによる記述を残してあります。
メニューで発生するタイミング
アプリケーション内で、ユーザーがメニューキーを押したとき、以下のようなイベントが発生します。
onCreateOptionMenu
onPrepareOptionMenu
onOptionMenuItemSelected
最初の「onCreateOptionMenu」は、初めてメニューキーが押されたときのみに呼び出されるもので、通常はここでメニューを生成させます。次の「onPrepareOptionMenu」は、メニューが表示される直前に毎回呼び出されます。ここでは、状態に合わせてメニュー項目の有効、無効などを設定します。最後の「onOptionMenuItemSelected」は、ユーザーがメニュー項目のどれか1つをタップしたあとに呼び出されるものです。
メニューは、基本的にはユーザーの操作により呼び出されます。このため、あらかじめタイミングを想定することはできません。必要なデータなどがあるなら、onCreateOptionMenuの中で生成するか、あるいはメニューを表示させるアクティビティのonCreateなどで準備しておく必要があります。
コードによるメニューの生成
まずは、コードを使ってメニューを作る場合を見てみることにしましょう。WorldClock.javaの233行目からが対応するコードになります。
@Override
public boolean onCreateOptionsMenu( Menu menu ) {
MenuItem itemAdd = menu.add( 0, MENU_ITEM_ADD, 0, R.string.menu_item_add );
MenuItem itemSet = menu.add( 0, MENU_ITEM_SET, 0, R.string.menu_item_set );
MenuItem itemDtSet = menu.add( 0, MENU_ITEM_DTSET, 0, R.string.menu_item_dt );
MenuItem itemEnd = menu.add( 0, MENU_ITEM_END, 0, R.string.menu_item_end );
itemAdd.setIcon( android.R.drawable.ic_menu_add );
itemSet.setIcon( android.R.drawable.ic_menu_preferences );
itemDtSet.setIcon( android.R.drawable.ic_menu_more );
itemEnd.setIcon( android.R.drawable.ic_menu_close_clear_cancel );
return true;
}
onCreateOptionsMenuは、Menuオブジェクトを引数として受け取り、これに対してメニューを追加していきます。あとから参照できるようにMenuItemクラスの変数で追加したメニュー項目を記憶します。これはあとからアイコンをセットするために必要になるからです。やり方としては、後述するメニューのIDを使って、menuオブジェクトからメニュー項目のオブジェクト(MeunItem)を見つける方法もあるのですが、それも記述が少し面倒になるため、ここでは、ローカル変数を作っています。
ここで、「MENU_ITEM_」で始まる定数は、以下のようにWorldClock.javaの55行目あたりで別途、定義してあります。
private static final int MENU_ITEM_ADD = 0;
private static final int MENU_ITEM_SET = 1;
private static final int MENU_ITEM_DTSET = 2;
private static final int MENU_ITEM_END = 99;
コードで記述するやり方はそれほど難しくないため、項目数がそんなにないのならコードで定義してもいいのですが、このように別途IDを定義しなければなりません。このIDは、あとでどのメニュー項目が押されたのかを検出するために使います。こういうIDを定数として管理するのは結構面倒で、まちがって重複した値を定義してしまうこともあります。間違いをなくすには、今回のようにダイレクトに定義するのではなくて、ひとつ前の値に「+1」をするようなコードを使うという方法もあります。ですがxmlを使えば、何も定義する必要はなく、管理がより簡単になります。
onCreateOptionsMenuでは、メニュー生成が成功したことを通知するためにtrueを返す必要があります。
メニューのアイコンはデフォルトのリソースを使用
前述の画面を見ると、メニューの4エリアそれぞれにアイコンが表示されています。しかしリソースの「res/drawable-*」を見てもファイルとしては「ic_btn_search.png」しかありません。
ここで参照されているアイコンは、すべてAndroid自身が持っているリソースを参照しているのです。これは、Android SDKのインストールフォルダにある「platforms」以下にあるフォルダに実際のデータが置かれており、これらに関しては、コード中で名前を指定するだけ(android.R.drawable.XXXX)で利用できます。
アプリケーションを実行するプラットフォームで図柄が違っています。たとえばAndroid 1.6の場合には「ic_menu_add」(android.R.drawable.ic_menu_add)は「platforms\android-4\data\res\drawable」にあります。ところがAndroid 2.1では「platforms\android-4\data\res」には「drawable-hdpi」「drawable-mdpi」「drawable-land-ldpi」の3つにic_menu_addが配置されています。これは解像度や画面の向きに応じて画像を自動的に切り替えることができるようにするためです。前記の名前で指定しておけば、実際の画面の表示密度に合わせて適当なものを選択してくれます。
なお、こうしたシステム側のリソースを使うには、SDKのインストールフォルダで、APIレベルごとになっているdata/resフォルダを調べてファイル名を得たら、“android.R.”を付けてリソース参照を行ないます。Android自身が表示に使っている画像のすべてをアプリケーションから利用できるわけでなく、このresフォルダ以下にあるもののみです。

この連載の記事
- 第11回 アプリケーションをAndroidマーケットに登録する
- 第10回 ブロードキャストへの応答とタイマ割り込み
- 第9回 Androidアプリで複数の項目を表示するリストビューを使う
- 第8回 Androidアプリに必要なダイアログを作る
- 第7回 Androidアプリの設定画面を作成する
- 第5回 インテントによるアプリケーションとアクティビティの呼出し
- 第4回 Androidアプリを構成する「アクティビティ」を実際に作る
- 第3回 アプリケーションの基本となる「アクティビティ」
- 第2回 開発したアプリをエミュレーターやデバッガ上でテストする
- 第1回 Androidアプリの開発環境であるEclipseの使い方を知る
- この連載の一覧へ