ListViewアイコンつき複数行リスト

アイコンつきのリスト。しかも複数行対応(^^)
それぞれの行数がすべて任意なので、結構使い勝手がいいです。
アイコンも前と後ろに任意で表示可能な優れもの(笑)

準備するもの
res/layout/com_multiline_row.xml
MultiLineListRow.java
MultiLineListRowAdaper.java
この3つのファイルをこぴぺしてください。

res/layout/com_multiline_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/row_prefix_image"
        android:layout_gravity="left|center_vertical"
        android:layout_weight="0"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content" />
    <LinearLayout
        android:id="@+id/row_list_area"
        android:layout_weight="1"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:orientation="vertical">
    </LinearLayout>
    <ImageView
        android:id="@+id/row_suffix_image"
        android:layout_gravity="right|center_vertical"
        android:layout_weight="0"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content" />
</LinearLayout>

MultiLineListRowAdapter.java

import java.util.List;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * 複行行表示可能なListのAdapterです。
 * 
 * templateはcom_multi_line_row.xmlにあるのでそちらも参照してください。

 *
 */
public class MultiLineListRowAdapter extends ArrayAdapter<MultiLineListRow> {
	
	private static final String TAG = "MultiLineListRowAdapter";
	
	/** displayed row */
	private List<MultiLineListRow> items;
	
	/** viewをクリックしたときのlistener */
	private OnClickListener listener;
	
	private LayoutInflater inflater;
	
	private int resourceId;
	
	public MultiLineListRowAdapter(Context context, int resourceId, List<MultiLineListRow> items) {
		this(context, resourceId, items, null);
	}
	
	public MultiLineListRowAdapter(Context context, int resourceId, List<MultiLineListRow> items, OnClickListener listener) {
		super(context, resourceId, items);
		this.resourceId = resourceId;
		this.items = items;
		this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		this.listener = listener;
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View view = convertView; 
		// 初回はnullがわたってくる。
		// 2回目以降は以前作成したものがわたってくるらしい。
		if (view == null) {
			// view = inflater.inflate(R.layout.com_multiline_row, null);
			view = inflater.inflate(resourceId, null);
		}
		view = populateView(position, view, parent);
		return view;
	}
	
	protected View populateView (int position, View convertView, ViewGroup parent) {
		
		Log.d(TAG, "populateView position [" + position + "]");
		MultiLineListRow item = items.get(position);
		if (item.getPrefixImageId() != null) {
			ImageView imageView = (ImageView) convertView.findViewById(R.id.row_prefix_image);
			imageView.setImageResource(item.getPrefixImageId());
		}
		
		if (item.getSuffixImageId() != null) {
			ImageView imageView = (ImageView) convertView.findViewById(R.id.row_suffix_image);
			imageView.setImageResource(item.getSuffixImageId());
		}
		
		LinearLayout layout = (LinearLayout) convertView.findViewById(R.id.row_list_area);
		// 全て消しているが・・・
		// パフォーマンスを考えると他の方法を探したほうがいいかも。
		// もっといい方法をご存知の方はご連絡下さい m(_ _)m
		layout.removeAllViews();
		Log.d(TAG, "PopulateTextView size [" + item.sieze() + "]");
		for (int i = 0, n = item.sieze(); i < n; i++) {
			TextView textView = new TextView(parent.getContext());
			textView.setText(item.getText(i));
			if (item.getTextSize(i) > 1) {
				textView.setTextSize(item.getTextSize(i));
			}
			Log.d(TAG, "Add TextView text [" + item.getText(i) + "]");
			layout.addView(textView, i);
		}
		
		if (listener != null) {
			convertView.setOnClickListener(listener);
		}
		return convertView;
	}
}

MultiLineListRow.java

/**
 * 複数行表示可能なListのRowです。

 *
 */
public interface MultiLineListRow {
	
	/**
	 * 先頭に付与するイメージのIDを取得します。
	 * 
	 * もし先頭にイメージを表示しない場合はnullが返却されます。
	 * @return 先頭に付与するイメージのID
	 */
	Integer getPrefixImageId();
	
	/**
	 * 末尾に付与するイメージのIDを取得します。
	 * 
	 * もし末尾にイメージを表示しない場合はnullが返却されます。
	 * @return 末尾に付与するイメージのID
	 */
	Integer getSuffixImageId();
	
	/**
	 * 表示するテキストの行数を取得します。
	 * @return テキストの行数
	 */
	int sieze();
	
	/**
	 * 表示するテキストを取得します。
	 * 
	 * @param position 表示する位置
	 * @return 表示するテキスト
	 */
	String getText(int position);
	
	/**
	 * 表示するテキストのサイズを取得します。
	 * 
	 * @param position 表示する位置
	 * @return 表示するテキストのサイズ
	 */
	float getTextSize(int position);
}

使い方

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ListView
	    android:id="@+id/list_view"
	    android:layout_width="fill_parent"
	    android:layout_height="fill_parent">
    </ListView>
    
</LinearLayout>

MultiLineListRowImpl.java
MultiLineRowはインタフェースなので。
実際は表示したいオブジェクトが直接実装してもいいけど、
サンプルで表示するために作成してあります。

import java.util.ArrayList;
import java.util.List;

public class MultiLineListRowImpl implements MultiLineListRow {
	
	private Integer prefixImage;
	private Integer suffixImage;
	
	List<String> texts;
	List<Float> size;
	
	public static MultiLineListRowImpl create() {
		
		MultiLineListRowImpl m = new MultiLineListRowImpl();
		m.texts = new ArrayList<String>();
		m.size = new ArrayList<Float>();
		return m;
	}
	public MultiLineListRowImpl prefixImage(Integer id) {
		this.prefixImage = id;
		return this;
	}
	public MultiLineListRowImpl suffixImage(Integer id) {
		this.suffixImage = id;
		return this;
	}
	public MultiLineListRowImpl addText(String text, float size) {
		this.texts.add(text);
		this.size.add(size);
		return this;
	}
	
	public MultiLineListRowImpl addText(String text) {
		this.texts.add(text);
		this.size.add(0f);
		return this;
	}
	
	public Integer getPrefixImageId() {
		return prefixImage;
	}

	public Integer getSuffixImageId() {
		return suffixImage;
	}

	public String getText(int position) {
		return texts.get(position);
	}

	public float getTextSize(int position) {
		return size.get(position);
	}

	public int sieze() {
		return texts.size();
	}
	
}

最後に表示するためのActivity

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;

public class SampleListView extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        populateContentsListView();
    }
    
    private void populateContentsListView() {
        ListView contentsView = (ListView) findViewById(R.id.list_view);
        
        // create dummy list
        List<MultiLineListRow> items = new ArrayList<MultiLineListRow>();
        
        items.add(MultiLineListRowImpl.create().addText("千年の孤独", 15));
        items.add(MultiLineListRowImpl.create().addText("コンテンツ1").addText("便利なリスト").prefixImage(R.drawable.icon));
        items.add(MultiLineListRowImpl.create().addText("今日の晩御飯", 20).addText("ラーメン").addText("餃子").prefixImage(R.drawable.icon).suffixImage(android.R.drawable.ic_media_play));
        contentsView.setAdapter(new MultiLineListRowAdapter(this, R.layout.com_multiline_row, items));
    }
}