2012年11月3日土曜日

リストビューをカスタマイズする

各行に表示させるアイテムの準備

まずは画像(Bitmap)とテキスト(String)を1つ持つアイテム用のクラスを用意します。ここではCustomDataクラスとします。

今回は説明のために簡易的にメンバに1つずつ持たせましたが、もちろん画像や文字列を複数表示させることは可能です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class CustomData {
    private Bitmap imageData_;
    private String textData_;
 
    public void setImagaData(Bitmap image) {
        imageData_ = image;
    }
 
    public Bitmap getImageData() {
        return imageData_;
    }
 
    public void setTextData(String text) {
        textData_ = text;
    }
 
    public String getTextData() {
        return textData_;
    }
}

そして、このアイテムを表示するレイアウトファイル(xml)も合わせて準備します。リストの各々の行のレイアウトということになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    <ImageView
        android:id="@+id/image"
        android:layout_width="60dip"
        android:layout_height="60dip"
        />
    <TextView
        android:id="@+id/text"
        android:choiceMode="singleChoice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

ArrayAdapterクラスの継承

さて、アイテム用のクラスが用意できたらそれらを扱うArrayAdapterクラスを準備します。

前回はArrayAdapter<String>のように文字列だけを表示していましたが、今回は独自のアイテム用のクラスCustomDataを扱えるようにArrayAdapterを継承して準備します。

CustomAdapterという名前で作ってみます。

getViewメソッドでListViewの各行に表示するアイテムを返すことになります。ですので、このgetViewメソッドをオーバーライドしてCustomDataクラスから必要なデータを取り出してViewを作る処理を記述します。
getViewメソッドは各行を表示しようとした時に呼ばれます。どの行を表示しようとしているかは引数のpositionで分かります。
まずはgetItemメソッドを利用してListの中から表示しようとしている行のアイテムを取得します。
次にconvertViewがnullかどうかを判断しています。スクロールするほどの行がある場合、メモリーの消費を抑えるためにViewを使い回します。そのためnullでない場合は使い回して、nullの場合のみ新しくViewを生成します。
あとはそのViewの各要素にitemのメンバに用意している画像と文字列をセットすればOKです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class CustomAdapter extends ArrayAdapter<CustomData> {
 private LayoutInflater layoutInflater_;
 
 public CustomAdapter(Context context, int textViewResourceId, List<CustomData> objects) {
 super(context, textViewResourceId, objects);
 layoutInflater_ = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 }
 
 @Override
 public View getView(int position, View convertView, ViewGroup parent) {
 // 特定の行(position)のデータを得る
 CustomData item = (CustomData)getItem(position);
 
 // convertViewは使い回しされている可能性があるのでnullの時だけ新しく作る
 if (null == convertView) {
 convertView = layoutInflater_.inflate(R.layout.custom_layout, null);
 }
 
 // CustomDataのデータをViewの各Widgetにセットする
 ImageView imageView;
 imageView = (ImageView)convertView.findViewById(R.id.image);
 imageView.setImageBitmap(item.getImageData());
 
 TextView textView;
 textView = (TextView)convertView.findViewById(R.id.text);
 textView.setText(item.getTextData());
 
 return convertView;
 }
}

表示してみる

さて、表示するアイテムのクラス、ArrayAdapterの準備が完了しました。 あとはそのアイテムのクラスのListを作成して、新しく作ったArrayAdapterの継承クラスのコンストラクタに与えて生成します。 そしてListViewのsetAdapterメソッドでセットすれば完了です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class ListViewSample2 extends Activity {
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        // リソースに準備した画像ファイルからBitmapを作成しておく
        Bitmap image;
        image = BitmapFactory.decodeResource(getResources(), R.drawable.tb);
 
        // データの作成
        List<CustomData> objects = new ArrayList<CustomData>();
        CustomData item1 = new CustomData();
        item1.setImagaData(image);
        item1.setTextData("1つ目?");
 
        CustomData item2 = new CustomData();
        item2.setImagaData(image);
        item2.setTextData("The second");
 
        CustomData item3 = new CustomData();
        item3.setImagaData(image);
        item3.setTextData("Il terzo");
 
        objects.add(item1);
        objects.add(item2);
        objects.add(item3);
 
        CustomAdapter customAdapater = new CustomAdapter(this, 0, objects);
 
        ListView listView = (ListView)findViewById(R.id.list);
        listView.setAdapter(customAdapater);
    }
}