ListViewでContextMenuを実装する

ListViewをContextMenuに設定する場合を書いときます。
Androidのメニューには大きく2つあります。

OptionMenuとContextMenuとですが、Androidアプリはこれらのメニューを実装するための手続きが異なります。

OptionMenuはAndroid端末のメニューボタンを押した時に動作するメニューのこと、
ContextMenuは画面上のあるコンポーネントを長押しした時に動作するメニューのことです。

使い分けですが、
「アプリケーション全体に関わる機能はOptionMenu、
選択した要素の補助的な機能はContextMenuで実装するのが望ましい」
とガイドラインに書いてあります。

Windowsの通常使うアプリケーションで言うと、
OptionMenuはウインドウ上部のメニューバー、
ContextMenuは右クリックしたときのメニューに相当するんじゃないかと勝手に考えます。

さて、今日のお題は以下のListViewのある要素に対するContextMenuを実装することです。

上記はListViewでJリーグの試合結果を表示しています。
任意のチームを長押しすることで、そのチームのサブメニューが表示されるイメージです。

それではコードを示します。

public class RankingListActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // ランキングリストを取得
        ArrayList list = (ArrayList) getIntent().getSerializableExtra("RANKING_LIST");
        setRank(list);

        // ListViewを生成
        ListView listView = (ListView) findViewById(R.id.mainListView01);

        // Adapterを生成
        SimpleAdapter adapter = new SimpleAdapter(
        		this,
        		list,
        		R.layout.ranking_item,
        		new String[]{"rank", "teamName", "win", "lose", "draw", "point"},
        		new int[]{R.id.rank, R.id.teamName, R.id.win, R.id.lose, R.id.draw, R.id.point});

        // ListViewにアダプタを設定
        listView.setAdapter(adapter);

        // コンテキストメニュー登録
        registerForContextMenu(listView);

    }


    /**
     * コンテキストメニュー生成時処理
     */
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
    	super.onCreateContextMenu(menu, view, info);
    	AdapterContextMenuInfo adapterInfo = (AdapterContextMenuInfo) info;
    	ListView listView = (ListView) view;
    	Map rankingMap = (Map) listView.getItemAtPosition(adapterInfo.position);

    	menu.setHeaderTitle((String) rankingMap.get("teamName"));
    	menu.add("直近10試合");
    	menu.add("年別成績");
    }
}

Activityを継承したRankingListActivityクラスが本画面を示します。
ランキングリストはチーム名、順位、勝ち点等の情報を含んだ
Mapオブジェクトを持つリストで、ListViewの1つの要素となります。

ContextMenuを実装するには、以下の2つを実装する必要があります。

ContextMenuの登録

registerForContextMenuメソッドを呼び出すことでContextMenuが使える状態になります。
引数はViewクラスのインスタンスを引き渡します。

コンテキストメニュー生成時の処理

onCreateContextMenuメソッドをオーバーライドする形で実装します。
ContextMenuオブジェクトのsetHeaderTitleでウインドウ上部のタイトルが、
addでメニューリスト部分のテキストを出力できます。

ListViewの場合は、押された要素の情報も欲しいでしょう。
押された要素の情報を取得するためには
ContextMenuInfoのインスタンスをAdapterContextMenuInfoでキャストし、
positionフィールドにアクセスすることで、押された要素のインデックスを取得することができます。
あとは、ViewをListViewにキャストして、getItemAtPositionで要素をもらってくるだけ。
ここがミソだったりします。

更に、ContextMenuのメニュー押下時の実装はまた今度の機会にでも・・・・・。