2.8. ListView の操作処理

サンプルアプリである「メモアプリ」の、メイン画面のリストの操作として、リストに表示されているアイテムを選択したときに編集画面を表示する処理と、 リストのアイテムを長押ししたときに「削除」のコンテキストメニューを表示し、削除の操作ができるような処理の追加について説明します。

メイン画面でのリスト操作イメージ
ここで必要になる処理としては、以下の3つとなります。
・ ListView のデータ選択時のイベント処理 (編集画面を表示)
・ ListView へのコンテキストメニュー追加
・ ListView のコンテキストメニュー選択時のイベント処理 (削除処理)

では、それぞれについて説明していきます。

ListView のデータ選択時のイベント処理

ListView のアイテム選択時のイベント処理を行うためには、ListView の setOnItemClickListener にリスナを登録して処理を行います。

このイベントで、編集画面を表示する処理を行います。選択したメモの内容を編集するための操作ですので、 編集画面は選択したアイテムの内容が表示された状態で画面表示されるようにします。

このイベントを処理す部分は以下のようになります。
(この処理は、MainActivity.java の onCreate メソッドで行います。)

ListView list = (ListView)findViewById(R.id.listView);
// ListView のアイテム選択イベント
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(
            AdapterView<?> parent, View view, int pos, long id) {
        // 編集画面に渡すデータをセットし、表示
        Intent intent = new Intent(MainActivity.this, EditActivity.class);
        intent.putExtra("NAME", mList.get(pos).get("filename"));
        intent.putExtra("TITLE", mList.get(pos).get("title"));
        intent.putExtra("CONTENT", mList.get(pos).get("content"));
        startActivity(intent);
    }
});

編集画面の表示は、2.5. 画面遷移処理 でも処理を行っていますので、それと同様の処理となります。
なお、メイン画面が持っているメモの内容を編集画面に渡す必要がありますので、Intent クラスの putExtra メソッドを使用してデータを渡します。
putExtra メソッドの第1引数はデータ識別の文字で、第2引数は渡すデータを設定します。
ここでは、NAME にファイル名、TITLE にタイトルの文字、CONTENT に内容の文字を設定してデータを渡しています。

また、編集画面では上記で設定されたデータを受け取る処理が必要となります。
この処理は、編集画面のファイル EditActivity.java の onCreate メソッドで行います。
編集画面が生成されるタイミングで、このデータを受け取ることになります。

以下、EditActivity.java ファイルの onCreate メソッドに追加する処理の内容です。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_edit);

    // タイトルと内容入力用の EditText を取得
    EditText eTxtTitle = (EditText)findViewById(R.id.eTxtTitle);
    EditText eTxtContent = (EditText)findViewById(R.id.eTxtContent);
    
    // メイン画面からの情報受け取り、EditTextに設定
    // (情報がない場合(新規作成の場合)は、設定しない)
    Intent intent = getIntent();
    String name = intent.getStringExtra("NAME");
    if (name != null) {
        mFileName = name;
        eTxtTitle.setText(intent.getStringExtra("TITLE"));
        eTxtContent.setText(intent.getStringExtra("CONTENT"));
    }
}

受け取る側では、Intent クラスの getStringExtra メソッドを使用してデータを受け取ります。
データを受け取り、NAME はメンバ変数へ、TITLE と CONTENT は、EditText のタイトルと内容に設定します。

なお、メイン画面のアクションバーの [追加] 項目が押下されたときには、メイン画面からのデータの受け渡しはありません。
その場合には、null が格納されていますので、この場合は設定しないようにします。

ListView へのコンテキストメニュー追加

ListView の項目長押し時に表示する、コンテキストメニューを追加します。
コンテキストメニューは、アクションバーのメニューと同様に、xml ファイルで項目を定義します。
まず、プロジェクト・エクスプローラの [MemoApp/res/menu] を右クリックし、
[新規 - Android XML ファイル] を選択してファイルを作成します。
新規 Android XML ファイルのダイアログが表示されます。
メイン画面でのリスト操作イメージ ファイル: に、main_context を設定し、「完了」ボタンを押下します。

main_content.xml ファイルが作成されますので、このファイルにコンテキストメニューとして表示する項目を記述していきます。
今回のメモアプリでは、コンテキストメニュー(ListView 長押し)で、「削除」を表示するので、main_context.xml ファイルの内容は、 以下のようになります。

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

</menu>

アクションバーに表示するメニューと同様に、項目は item タグで記述します。「削除」の項目だけなので、item が1つのみの記述となります。

また、title に設定している文字列は、strings.xml ファイルに定義しますので、以下を追加します。

<string name="context_del">削除</string>


次に、メイン画面にコンテキストメニューを作成する処理を追加します。
コンテキストメニューの作成処理は、Activity クラスの onCreateContextMenu メソッドで行います。
ここで、上記で作成した main_context.xml のレイアウトを設定することになります。
この部分の処理は以下のようになります。

// コンテキストメニュー作成処理
    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
        super.onCreateContextMenu(menu, view, info);
        getMenuInflater().inflate(R.menu.main_context, menu);
    }

アクションバーのメニュー作成処理と同様に、上記のように設定することで作成したレイアウト main_context.xml が、 コンテキストメニューとして設定されます。

最後に、上記コンテキストメニューを表示する対象として、ListView を登録します。
この処理は、メイン画面クラスが作成されるときに設定しますので、onCreate メソッドに追加します。

// コンテキストメニューに ListView を登録
registerForContextMenu(list);

ここまでで、ListView を長押しすると、コンテキストメニューとして 「削除」 が表示されるようになります。
次に、コンテキストメニュー 「削除」 が選択されたときに、対象のデータを削除する処理を追加します。

ListView のコンテキストメニュー選択時のイベント処理 (削除処理)

先ほど作成したコンテキストメニューを選択したときのイベント処理を作成していきます。
コンテキストメニューで表示される 「削除」 を選択したときに、リストのデータと保存されているファイルを削除する処理を行います。

コンテキストメニューが選択されたときのイベントは、onContextItemSelected メソッドで処理します。
この中に、削除の処理を追加します。

// コンテキストメニュー選択処理
@Override
public boolean onContextItemSelected(MenuItem item) {
    AdapterContextMenuInfo info = (AdapterContextMenuInfo)item.getMenuInfo();
    
    switch(item.getItemId()) {
    case R.id.context_del:
        // [削除] 選択時の処理
        // ファイル削除
        if (this.deleteFile(mList.get(info.position).get("filename"))) {
            Toast.makeText(this, R.string.msg_del, Toast.LENGTH_SHORT).show();
        }
        // リストからアイテム処理
        mList.remove(info.position);
        // ListView のデータ変更を表示に反映
        mAdapter.notifyDataSetChanged();
        break;
    default:
        break;
    }
    return false;
}

また、Toastで表示する文字の定義を、strings.xml に追加します。

<string name="msg_del">削除しました。</string>


アクションバーのメニュー選択イベントと同様に、item.getItemId でメニューの id を取得し、処理わけを行います。
今回は、「削除」だけなので、レイアウトファイルの item に指定した id である context_del で削除処理をします。

ファイルの削除は、編集画面で行ったときと同様に deleteFile メソッドを使用します。
リストの各項目のファイル名は、mList のデータであるMapの filename キーに保存されていますので、これを取得してファイルを削除します。
リストで選択した項目のインデックスは、info.position で取得することができますのでこれを使用します。

リストのデータ削除は、リストのデータである mList の remove メソッドを使用します。
上記と同様に info.position のインデックスのデータを削除します。
そして、削除後にリストの表示を更新するために、ListView に設定したアダプタ mAdapter の notifyDataSetChanged メソッドを呼び出します。

これで、メイン画面のリスト選択時の編集画面表示と、リスト長押しで削除する処理の追加は完了です。

この状態でアプリを実行し、メイン画面でリストの項目を選択すると、その内容が表示された状態で編集画面が表示されます。
また、リストの項目を長押しすると、「削除」のコンテキストメニューが表示され、「削除」を選択するとリストから項目が削除されます。
(保存されているファイルも削除されます。)

これで、メモアプリの作成はすべて完了です。



次は・・・
メモアプリのソースファイルの完全版と、各処理について簡単な説明をします。
2.9. メモアプリの完成ソース