Androidで折りたたみ式リストビュー(ExpandableListView)を使う方法をメモします。
#ExpandableListViewを持ったレイアウト
##レイアウトの設定
まず、ExpandalbeListViewを持ったレイアウトを作成します。
レイアウトに ExpandableListView をドロップし下記のようにします。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<ExpandableListView
android:id="@+id/expandableListView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:layout_marginTop="14dp" >
</ExpandableListView>
</RelativeLayout>
#ExpandableListViewを使用したActivity
次に、Activityを作成します。
ExpandableListViewで情報を表示するには、SimpleExpandableListAdapterを使います。
SimpleExpandableListAdapterを使用することで、簡単にExpandableListViewへデータを渡すことができます。
リストとして表示したい情報をSimpleExpandableListAdapterへ格納するため、下記の順にMapを作成します。
- グループの親項目用のリストを作る
- リスト項目として表示したい子要素全体用のリストを作る
- グループの親項目用のMapに情報を格納する
- 各グループ別のリスト項目用のリストを作る
- 各グループ別のリスト項目用のMapに情報を格納する
- 子要素全体用のリストに、各グループ別のリスト項目用リストを格納する
- グループの親項目用のリストと、子要素全体用のリストをSimpleExpandableListAdapterへ格納する
では、実際にコードにします。
##各データの格納
まず、グループの親項目用のMapに、表示したい内容を格納します。
int PARENT_DATA = 3;
// グループの親項目用のリスト
List<Map<String, String>> parentList = new ArrayList<Map<String, String>>();
// 親リストに表示する内容を生成
for (int i = 0; i < PARENT_DATA; i++) {
Map<String, String> parentData = new HashMap<String, String>();
parentData.put("title", "title" + Integer.toString(i));
// グループの親項目用のリストに内容を格納
parentList.add(parentData);
}
次に、子要素となる内容を格納します。
int CHILD_DATA = 3;
// 子要素全体用のリスト
List<List<Map<String, String>>> allChildList = new ArrayList<List<Map<String, String>>>();
// 子要素として表示する文字を生成
for (int i = 0; i < PARENT_DATA; i++) {
// 各グループ別のリスト項目用のリスト
List<Map<String, String>> childList = new ArrayList<Map<String, String>>();
// リスト項目用データ格納
for (int j = 0; j < CHILD_DATA; j++) {
Map<String, String> childData = new HashMap<String, String>();
childData.put("TITLE", "子要素" + Integer.toString(j));
childData.put("SUMMARY", "概要" + Integer.toString(j));
// リストに文字を格納
childList.add(childData);
}
// 子要素全体用のリストに各グループごとデータを格納
allChildList.add(childList);
}
##アダプタに格納
そして、作成した情報をアダプターに格納します。
// アダプタを作る
SimpleExpandableListAdapter adapter =
new SimpleExpandableListAdapter(
this,
parentList,
android.R.layout.simple_expandable_list_item_1,
new String[] { KEY1 },
new int[] { android.R.id.text1, android.R.id.text2 },
allChildList,
android.R.layout.simple_expandable_list_item_2,
new String[] { KEY1, KEY2 },
new int[] { android.R.id.text1, android.R.id.text2 }
);
//生成した情報をセット
ExpandableListView lv = (ExpandableListView)findViewById(R.id.expandableListView1);
lv.setAdapter(adapter);
なお、SimpleExpandableListAdapterクラスのコンストラクタは下記のようになっています。
引数 | 変数 | 説明 |
---|---|---|
1 | Context context | ExpandableListViewが関連付けられるContext |
2 | List< ? extends Map> groupData | Group(親)のリスト |
3 | int expandedGroupLayout | Group(親)のレイアウト |
4 | String[] groupFrom | Group(親)のリストで表示するMapのキー |
5 | int[] groupTo | Group(親)のレイアウト内での文字を表示するTextViewのID |
6 | List< ? extends List< ? extends Map< String, ?>>> | Child(子)のリスト |
7 | int childLayout | Child(子)のレイアウト |
8 | String[] childFrom | Child(子)のリストで表示するMapのキー |
9 | int[] childTo | Child(子)のレイアウト内での文字を表示するTextViewのID |
##リストの項目がクリックされた時の処理
リストの項目がクリックされた時の処理を作るには、OnChildClickListenerインターフェースのonChildClickメソッドを使います。
// リスト項目がクリックされた時の処理
lv.setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View view,
int groupPosition, int childPosition, long id) {
ExpandableListAdapter adapter = parent.getExpandableListAdapter();
// クリックされた場所の内容情報を取得
@SuppressWarnings("unchecked")
Map<String, String> item = (Map<String, String>)adapter.getChild(groupPosition, childPosition);
// アラート表示
AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this);
dlg.setTitle("クリック!")
.setMessage(item.get(KEY1))
.setPositiveButton("OK", null)
.show();
return false;
}
});
onChildClickメソッドの引数は下記のようになっています。
引数 | 変数 | 説明 |
---|---|---|
1 | ExpandableListView parent | イベントが起きたExpandableListView |
2 | View view | 選択されたリスト項目 |
3 | int groupPosition | 選択されたリスト項目の親グループの位置(0~) |
4 | int childPosition | 選択されたリスト項目の、グループ内での位置(0~) |
5 | long id | 選択されたリスト項目のIDを示す値(0~) |
##グループの親項目がクリックされた時の処理
グループの親項目が選択された時の処理を作るには、OnGroupClickListenerインターフェースのonGroupClickメソッドを使います。
// グループの親項目がクリックされた時の処理
lv.setOnGroupClickListener(new OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View view,
int groupPosition, long id) {
ExpandableListAdapter adapter = parent.getExpandableListAdapter();
// クリックされた場所の内容情報を取得
@SuppressWarnings("unchecked")
Map<String, String> item = (Map<String, String>)adapter.getGroup(groupPosition);
// アラート表示
AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this);
dlg.setTitle("クリック!")
.setMessage(item.get(KEY1))
.setPositiveButton("OK", null)
.show();
return false;
}
});
onGroupClickメソッドの引数は下記のようになっています。
引数 | 変数 | 説明 |
---|---|---|
1 | ExpandableListView parent | イベントが起きたExpandableListView |
2 | View view | 選択されたグループの親項目 |
3 | int groupPosition | 選択されたグループの親項目の位置(0~) |
4 | long id | 選択されたグループの親項目のIDを示す値(0〜) |
#完成ソース
上記の処理をまとめると、下記のようなソースになります。
package com.yuuweb.expandablelistviewtest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.SimpleExpandableListAdapter;
import android.app.Activity;
import android.app.AlertDialog;
public class MainActivity extends Activity {
private final String KEY1 = "TITLE";
private final String KEY2 = "SUMMARY";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int PARENT_DATA = 3;
// 親ノードのリスト
List<Map<String, String>> parentList = new ArrayList<Map<String, String>>();
// 親ノードに表示する内容を生成
for (int i = 0; i < PARENT_DATA; i++) {
Map<String, String> parentData = new HashMap<String, String>();
parentData.put(KEY1, "タイトル" + Integer.toString(i));
// 親ノードのリストに内容を格納
parentList.add(parentData);
}
int CHILD_DATA = 3;
// 全体の子ノードのリスト
List<List<Map<String, String>>> allChildList = new ArrayList<List<Map<String, String>>>();
// 子要素として表示する文字を生成
for (int i = 0; i < PARENT_DATA; i++) {
// 子要素全体用のリスト
List<Map<String, String>> childList = new ArrayList<Map<String, String>>();
// 各子ノード用データ格納
for (int j = 0; j < CHILD_DATA; j++) {
Map<String, String> childData = new HashMap<String, String>();
childData.put(KEY1, "子要素" + Integer.toString(j));
childData.put(KEY2, "概要" + Integer.toString(j));
// 子ノードのリストに文字を格納
childList.add(childData);
}
// 全体の子ノードリストに各小ノードリストのデータを格納
allChildList.add(childList);
}
// アダプタを作る
SimpleExpandableListAdapter adapter =
new SimpleExpandableListAdapter(
this,
parentList,
android.R.layout.simple_expandable_list_item_1,
new String[] { KEY1 },
new int[] { android.R.id.text1, android.R.id.text2 },
allChildList,
android.R.layout.simple_expandable_list_item_2,
new String[] { KEY1, KEY2 },
new int[] { android.R.id.text1, android.R.id.text2 }
);
//生成した情報をセット
ExpandableListView lv = (ExpandableListView)findViewById(R.id.expandableListView1);
lv.setAdapter(adapter);
// リスト項目がクリックされた時の処理
lv.setOnChildClickListener(new OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View view,
int groupPosition, int childPosition, long id) {
ExpandableListAdapter adapter = parent.getExpandableListAdapter();
// クリックされた場所の内容情報を取得
@SuppressWarnings("unchecked")
Map<String, String> item = (Map<String, String>)adapter.getChild(groupPosition, childPosition);
// アラート表示
AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this);
dlg.setTitle("クリック!")
.setMessage(item.get(KEY1))
.setPositiveButton("OK", null)
.show();
return false;
}
});
// グループの親項目がクリックされた時の処理
lv.setOnGroupClickListener(new OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View view,
int groupPosition, long id) {
ExpandableListAdapter adapter = parent.getExpandableListAdapter();
// クリックされた場所の内容情報を取得
@SuppressWarnings("unchecked")
Map<String, String> item = (Map<String, String>)adapter.getGroup(groupPosition);
// アラート表示
AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this);
dlg.setTitle("クリック!")
.setMessage(item.get(KEY1))
.setPositiveButton("OK", null)
.show();
return false;
}
});
}
}
以上です。