リストタップのイベントリスナ
では、前回解説した手順に従って、アクティビティクラスにソースコードを記述していきましょう。
リスナクラス作成
ListViewSampleActivityのonCreate()メソッドの下に以下のソースコードを記述します。
public class ListViewSampleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
~省略~
}
private class ListItemClickListener implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
}
}
前回同様、リスナクラスとしてListItemClickListenerクラスをprivateメンバクラスとして追記しています。ListViewのタップというイベントに対するリスナインターフェースはAdapterView.OnItemClickListenerですので、これをimplementsします。
処理を記述
AdapterView.OnItemClickListenerインターフェースをimplementsした時点で、onItemClick()メソッドを実装する必要がありますので、ここに処理を記述します。
onItemClick()メソッド内に以下のソースコードを記述します。
public class ListViewSampleActivity extends AppCompatActivity {
~省略~
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String item = (String) parent.getItemAtPosition(position); // (1)
String show = "あなたが選んだ定食: " + item; // (2)
Toast.makeText(ListViewSampleActivity.this, show, Toast.LENGTH_LONG).show(); // (3)
}
}
}
処理を記述するにあたって、onItemClick()メソッドの引数を理解しておく必要があります。
第1引数:AdapterView<?> parent
タップされたリスト全体を表します。タップイベントそのものはリスト中の1行に対して起こりますが、その1行を含むリスト全体が引数として渡されます。なお、AdapterViewクラスは、ListViewやSpinnerの親クラスです。
第2引数:View view
タップされた1行中の画面部品そのものを表します。ListViewは1行内に、例えばTextView2個とチェックボックス1個のように、様々な画面部品を入れることが可能です。その場合、タップした位置でタップした画面部品が変わってきます。その画面部品が渡ってくるのがこの引数です。なお、今回はリスト1行中にTextViewが1個のリストです。
第3引数:int position
タップされた行番号を表します。ただし、0始まりです。今回のサンプルでいえば、「から揚げ定食」が0、「ハンバーグ定食」が1、…、のようになります。
第4引数:long id
後述のSimpleCursorAdapterを利用する場合、DBの主キーの値を表します。それ以外は第3引数のpositionと同じ値が渡されます。
これらの引数を利用して、まずタップされた定食名を取得します。その処理が(1)です。
(1)では、第1引数で渡されたparentを利用します。parentはAdapterView型ですが、このクラスのメソッドにgetItemAtPosition()というのがあります。これは、引数として行番号を渡すと、リストデータのうちでその行番号に該当するデータを返してくれます。この引数として、第3引数のpositionを渡すことで、タップされた行のデータを取得することができます。
ただし、getItemAtPosition()の戻り値の型はObject型です。これを、リストデータを構成しているデータ型にキャストする必要があります。今回のリストデータはすべてString型となっていますので、Stringにキャストします。これで、定食名が取得できます。
[Note]第2引数の利用
上記では、第1引数と第3引数を利用しました。一方で、第2引数がタップされた画面部品そのものを表しますので、こちらを利用することもできます。その場合は、以下の2行を記述します。
TextView tvText = (TextView) view; String item = tvText.getText().toString();
次に、トースト表示の処理を記述します。その前に、(2)でトースト表示用の文字列を生成しています。
実際のトースト表示は(3)です。これは、
Toast.makeText(引数1, 引数2, 引数3).show();
の記述で表示されると理解していれば問題ありません。
引数1はトーストを表示させるActivityオブジェクトを指定します。このことを、Android開発では「コンテキスト」といいます。これは、通常「アクティビティクラス名.this」と記述します。
引数2は表示文字列を指定します。
引数3はトーストが表示される長さで、Toastクラスの定数で指定します。「Toast.LENGTH_LONG」(長い)、「Toast.LENGTH_SHORT」(短い)の2種しかありません。
[Note]コンテキスト
Android開発では、コンテキストは重要な概念で、さまざまな引数で使用されます。実は、Activityクラスの親クラスとしてContextクラス(リファレンスページ参照)というのが存在し、例えば、ToastのmakeText()の第1引数では、このクラスが型として指定されています(リファレンスページ参照)。このコンテキストの指定としては、通常Activityインスタンスを指定します。その際、サンプルなどでは単に「this」という記述がよくみられます。Javaでは「this」は自分自身のインスタンスを指しますが、Android開発でよくみられるネストクラスの場合、この「this」が何を指すのかをよくよく考えないと誤動作することになります。そういったことを避けるためにも「アクティビティクラス名.this」という記述は安全です。
リスナ設定
最後に、リスナを設定します。onCreate()メソッド内に以下の2行を追記します。
public class ListViewSampleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
~省略~
ListView listView = (ListView) findViewById(R.id.lv_menu);
listView.setOnItemClickListener(new ListItemClickListener());
}
~省略~
}
リスナを設定するListViewを取得し、リスナ設定メソッドsetOnItemClickListener()に先に作成したリスナクラスListItemClickListenerをnewして渡しています。
これで、一通りのコーディングが終了しました。
アプリを再起動し、動作確認を行ってください。リストをタップすると、以下のように画面下部にぼわーと文字列が表示され、自動的に消えていきます。これがトーストです。
