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


以前の記事(リストビューを使ってデータを一覧表示する)でリストビューを扱う方法がありましたが、文字だけを表示させていました。

今回は画像と文字を表示させてみようと思います。

では続きで説明して行きます。

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

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

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

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)も合わせて準備します。リストの各々の行のレイアウトということになります。

<?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です。

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メソッドでセットすれば完了です。

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);
    }
}
9 Comments