ListAdapterについて調べてみた(2) SimpleAdapter編その1
前回ArrayAdapterを使ってみました。
ArrayAdapterは,一つのTextViewだけセルごとに値を設定する場合,getViewメソッドをオーバーライドしたりせず非常に少ないコード量で書けます。
しかし,TextViewではなくImageViewの要素をセルごとに設定したり,セルごとに複数のTextViewに値を設定したり,画像と文字列両方セルごとに設定したりということは,getViewメソッドのオーバーライドメソッドなしには実現できません。
このようなことはSimpleAdapterを使えば,比較的容易にそしてgetViewメソッドのオーバーライドなしに少ないコード量で書けます。
具体例と一緒に使い方を見ていきます。
やりたいことと設定
こんなクラスがあるとします。
public class ColorItem { private final String nameEnglish; private final String nameJapanese; private final int imageId; public ColorItem(String nameEnglish, String nameJapanese, int imageId) { this.nameEnglish = nameEnglish; this.nameJapanese = nameJapanese; this.imageId = imageId; } public String getNameEnglish() { return nameEnglish; } public String getNameJapanese() { return nameJapanese; } public int getImageId() { return imageId; } }
こんなレイアウトXMLファイルがあるとします。
res/layout/list_item_for_simple_adapter.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="70dp" > <TextView android:id="@+id/name_english_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="20dp" android:layout_marginTop="15dp" android:text="英語名" > </TextView> <TextView android:id="@+id/name_japanese_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="15dp" android:layout_marginLeft="20dp" android:text="日本語名" > </TextView> <ImageView android:id="@+id/color_image_view" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_margin="10dp" /> </RelativeLayout>
ColorItemのListのインスタンスがあり,そのインスタンスの情報をListViewに表示したいです。
list_item_for_simple_adapterをセルのレイアウトとし,ColorItemクラスのインスタンスの情報をセットするためのSimpleAdapterインスタンスを作成します。
ColorItemのnameEnglishの文字列の値を上記レイアウトXMLファイル中のidがname_english_text_viewのTextView中にセットし,nameJapaneseの文字列をidがname_japanese_text_viewのTextView中にセットし,imageIdの値をidとする画像リソースをcolor_image_viewというidのImageViewにセットします。
サンプルコード
public class SimpleAdapterSampleActivity extends ListActivity { private static final String KEY_NAME_ENGLISH = "name_english"; private static final String KEY_NAME_JAPANESE = "name_japanese"; private static final String KEY_IMAGE_ID = "image_id"; private static final String[] FROM = new String[] { KEY_NAME_ENGLISH, KEY_NAME_JAPANESE, KEY_IMAGE_ID }; private static final int[] TO = new int[] { R.id.name_english_text_view, R.id.name_japanese_text_view, R.id.color_image_view }; private static final List<ColorItem> COLOR_ITEM; static { COLOR_ITEM = new ArrayList<ColorItem>(); COLOR_ITEM.add(new ColorItem("Blue", "青", R.drawable.blue)); COLOR_ITEM.add(new ColorItem("Cyan", "シアン", R.drawable.cyan)); COLOR_ITEM.add(new ColorItem("Green", "緑", R.drawable.green)); COLOR_ITEM.add(new ColorItem("Magenta", "マゼンタ", R.drawable.magenta)); COLOR_ITEM.add(new ColorItem("Red", "赤", R.drawable.red)); COLOR_ITEM.add(new ColorItem("Yellow", "黄色", R.drawable.yellow)); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); List<ColorItem> colorItemList = new ArrayList<ColorItem>(COLOR_ITEM); List<Map<String, ?>> data = colorItemListToMapList(colorItemList); int layoutResourceId = R.layout.list_item_for_simple_adapter; SimpleAdapter adapter = new SimpleAdapter(this, data, layoutResourceId, FROM, TO); setListAdapter(adapter); } private List<Map<String, ?>> colorItemListToMapList(List<ColorItem> colorItemList) { List<Map<String, ?>> data = new ArrayList<Map<String, ?>>(); for (ColorItem colorItem : colorItemList) { data.add(colorItemToMap(colorItem)); } return data; } private Map<String, ?> colorItemToMap(ColorItem colorItem) { Map<String, Object> map = new HashMap<String, Object>(); map.put(KEY_NAME_ENGLISH, colorItem.getNameEnglish()); map.put(KEY_NAME_JAPANESE, colorItem.getNameJapanese()); map.put(KEY_IMAGE_ID, Integer.valueOf(colorItem.getImageId())); return map; } }
次の節から詳しく中身を見ていきます
SimpleAdapterのコンストラクタ
SimpleAdapterコンストラクタは一つで
public SimpleAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
のみとなっています。
それぞれの引数の意味を簡単に説明すると,
第2引数は,キーがString型のMapのList(詳しくは後述)
第3引数は,セルのレイアウトXMLファイルのid
第4引数は,第2引数のMapのキーの配列
第5引数は,第3引数のレイアウトXMLファイル内のビューのidの配列
です。
まずColorItemの各フィールドの値とビューのidを紐付ける仲介を行うマップのキーを定義します。
static final String KEY_NAME_ENGLISH = "name_english"; // 英語名のデータとビューのためのキー static final String KEY_NAME_JAPANESE = "name_japanese"; // 日本語名のデータとビューのためのキー static final String KEY_IMAGE_ID = "image_id"; // 画像のデータとビューのためのキー
このキーを使って,SimpleAdapterの第4引数を作ります。
static final String[] FROM = new String[] { KEY_NAME_ENGLISH, KEY_NAME_JAPANESE, KEY_IMAGE_ID };
次はint[]型の第5引数です。
第4引数の配列は,英語名,日本語名,画像idの順番でキーが並んでいます。
その順番で,それぞれのキーと対応するビューのidを要素とするint型の配列を作ります。それそれのビューのidは,第3引数のレイアウト中のビューのidでないといけません。
static final int[] TO = new int[] { R.id.name_english_text_view, R.id.name_japanese_text_view, R.id.color_image_view };
最後に第2引数です。これはキーがString型のMapのListになっています。
SimpleAdapterを使うためには表示したいデータをこの型に変換する必要があります。
コンストラクタの第2引数 キーがString型のMapのリスト
コンストラクタの第2引数はキーがString型のMapのListです。
まずColorItemのインスタンスを,キーがString型のMapに変換するメソッドを作ります。
private Map<String, ?> colorItemToMap(ColorItem colorItem) { Map<String, Object> map = new HashMap<String, Object>(); map.put(KEY_NAME_ENGLISH, colorItem.getNameEnglish()); map.put(KEY_NAME_JAPANESE, colorItem.getNameJapanese()); map.put(KEY_IMAGE_ID, Integer.valueOf(colorItem.getImageId())); return map; }
キーは第4引数にも用いた文字列で,バリューはそのキーと対応するColorItem型のフィールドです。
このメソッドを使って,ColorItemのListを変換するメソッドを定義します。
private List<Map<String, ?>> colorItemListToMapList(List<ColorItem> colorItemList) { List<Map<String, ?>> data = new ArrayList<Map<String, ?>>(); for (ColorItem colorItem : colorItemList) { data.add(colorItemToMap(colorItem)); } return data; }
SimpleAdapterのインスタンスの作成
ActivityのonCreate内で,
List<Map<String, ?>> data = colorItemListToMapList(colorItemList); int layoutResourceId = R.layout.list_item_for_simple_adapter; SimpleAdapter adapter = new SimpleAdapter(this, data, layoutResourceId, FROM, TO);
とすれば,前述のやりたいことを実現できるSimpleAdapterが作成できます。
まとめ
SimpleAdapterを使って,セルごとに複数のTextViewに文字列とImageViewに画像を設定することができました。