ジャンル不定の日記です。

SimpleAdapterでListView

引き続き、Androidアプリ開発の勉強。

前回はArrayAdapterでのListView作成をやってみたが、ArrayAdapterだと1行に2カラム以上あるリストが作成できないね。
あと、ArrayAdapter.add()で1行ずつ追加したが、クリック等のイベントを設定する場合、リスト中のクリックされた行の行番号しか取れなそうなんで、
アイテムに対応した値を取得しようと思ったら別途多次元配列のようなものを用意しておかないと無理だね。
すごく不便。

というわけで、ArrayAdapterと別のSimpleAdapterを試してみた。
こちらはArrayAdapter以上にわかりにくかったが、まあArrayAdapterである程度わかったから、ハマりはしなかった。
ArrayAdapterは空で作成してaddで1行ずつ追加できたが、SimpleAdapterはオブジェクト作成時に一括でデータを渡す以外に方法はないみたい。

SimpleAdapter作成時に渡すデータは、MapのListという形式。

Mapは、
HashMap map=new HashMap();
map.put("key1","value1-"+i);
map.put("key2","value2-"+i);
って感じで、keyとvalueの値を複数登録できる型。
Perlで言うところのハッシュだね。
使うにはjava.util.HashMapをimportする必要がある。

Listは、
ArrayList list=new ArrayList();
data.add(data);
これはPerlで言うところの普通の配列だね。
Javaの配列は宣言時に容量が決まるので後から拡張ができない?
Listは容量不定で作成でき、addで拡張しつつ追加できる。
ってことぽい。
使うにはjava.util.ArrayListをimportする必要がある。

今回SimpleAdapterに渡すデータはMapのListなので、
        ArrayList data=new ArrayList();
        for(int i=0;i<10;i++){
            HashMap map=new HashMap();
            map.put("key1","value1-"+i);
            map.put("key2","value2-"+i);
            data.add(map);
        }
こんな感じで作った。

SimpleAdapterの作成は、
SimpleAdapter sa=new SimpleAdapter(this,data,android.R.layout.simple_list_item_2,new String[]{"key1","key2"},new int[]{android.R.id.text1,android.R.id.text2});
こんな感じ。
1番目の引数はContext。
2番目の引数はデータ(上で作成した、MapのList)。
3番目の引数はレイアウト。
4番目の引数はStringの配列。2番目の引数のデータ内のMapから、ここで指定した文字列に対応した値がリスト表示内容となる。
5番目の引数はカラムに適用するViewのID?の配列。これはレイアウトが対応したものでないと表示されないぽい。

最終的に、
package com.example.list;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import java.util.ArrayList;
import java.util.HashMap;

public class MainActivity extends Activity{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ArrayList data=new ArrayList();
        for(int i=0;i<10;i++){
            HashMap map=new HashMap();
            map.put("key1","value1-"+i);
            map.put("key2","value2-"+i);
            data.add(map);
        }
        ListView lv=new ListView(this);
        SimpleAdapter sa=new SimpleAdapter(this,data,android.R.layout.simple_list_item_2,new String[]{"key1","key2"},new int[]{android.R.id.text1,android.R.id.text2});
        lv.setAdapter(sa);
        setContentView(lv);
    }
}
こんな感じのコードになったんだが、


↑こんな表示。
前回のArrayAdapterを試した時はレイアウトにandroid.R.layout.simple_list_item_1を使用したが、android.R.layout.simple_list_item_1は1行にTextViewが一つしか設置できない。
今回のandroid.R.layout.simple_list_item_2は上段にandroid.R.id.text1を表示して、下段にandroid.R.id.text2を表示する2段式。
だが、これ2つしかデータ表示できないし、用意されたレイアウトだと横並べとかできないぽい。
いくつもファイル小分けにしたくないからJavaのソースファイル一つでカスタマイズしたかったが、レイアウトファイル使わないとダメぽいね・・・


ArrayAdapterにはaddメソッドがあるが。SimpleAdapterには後から追加したりするメソッドはないので困りそうだが、
ListViewが継承しているAbsListViewクラスにinvalidateViews()メソッドがあって、これ使うとListViewが再構築される。
SimpleAdapter作成後にListを更新して、ListView.invalidateViews()で再構築をしてみたが、反映した。
というわけで、addがないのは問題無さそう。

表示内容が1行に1個ならArrayAdapterでもいいんだが、
ArrayAdapterを使う場合でもクリック等のイベントで取得できるのが行番号だけとなると、表示内容以外に行番号に対応したIDを持った多重配列を用意しないと使いにくいと思うのし、Javaの配列は容量が固定ぽいからListの方が使いやすそうだし、
ArrayAdapterを使う場合とSimpleAdapterを使う場合で、コード量の差は1,2行しか変わらなそう。
それなら、常にSimpleAdapterを使ってコードを統一しちゃったほうが良さそう。