とある学生の技術Blog

半分くらい自分の備忘録として…

SQLiteから値を取り出し、カスタマイズしたリストビューに表示する方法

今回は自分もかなり苦労したところです。
結構複雑なのでじっくり読むことをおすすめします。

タイトルからは伝わりづらいかもしれませんが、
リストの横にアイコン画像を付けたカスタムリストビューへSQLiteから取り出したデータを反映したい
とまぁこんな感じのことを説明していきます。



※SQLiteOpenHelperの内容については普通にSQLiteを使う時と変わりないので割愛させて頂きます。

まずはリストの一つ一つの部分のレイアウトです。

row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:paddingTop="6dip"
    android:paddingBottom="6dip"
    android:paddingLeft="21dip"
    android:paddingRight="11dip"
    >
    
<ImageView
    android:id="@+id/icon"
    android:paddingRight="14dip"
    android:layout_width="53dp"
    android:layout_height="53dp"
    />
    
<TextView
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="#000000"
    android:textSize="25sp"
    android:layout_gravity="center_vertical"
/>

</LinearLayout>

ここでは普通にアイコン用のImageViewと文字列用のTextViewが配置してあります。
今回はArrayAdapterを拡張した独自アダプターを使用します。
以下はデータの補助をする役割的な位置のクラスです。

public class ListItems {
	
	private int iconRes;
	private String text;
	
	public ListItems(int iconRes, String text) {
		this.iconRes = iconRes;
		this.text = text;
	}
	
	public int getIconRes() {
		return iconRes;
	}
	
	public String getText() {
		return text;
	}
	
	public void setIconRes(int iconRes) {
		this.iconRes = iconRes;
	}
	
	public void setText(String text) {
		this.text = text;
	}
}

次にArrayAdapterを継承した独自アダプター。

public class ListViewAdapter extends ArrayAdapter<ListItems> {
	
	private LayoutInflater inflater;
	private int tvResId;
	private List<ListItems> items;
	
	public ListViewAdapter(Context context, int tvResId, List<ListItems> items) {
		super(context, tvResId, items);
		
		this.tvResId = tvResId;
                this.items = items;
		
		inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View view = null;
		
		if(convertView != null) {
			view = convertView;
		}else {
			view = inflater.inflate(tvResId, null);
		}
		
		ListItems item = items.get(position);
		
		ImageView imageView = (ImageView)view.findViewById(R.id.icon);
		imageView.setImageRes(item.getIconRes());
		
		TextView textView = (TextView)view.findViewById(R.id.text);
		textView.setText(item.getText());
		
		return view;
	}
	
}

最後にデータをつめてアダプターに渡すMainActivity。
MainActivity.java

public class MainActivity extends ListActivity {

	private SQLiteDatabase db = null;
	private SampleSQLiteOpenHelper helper = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        helper = new SampleSQLiteOpenHelper(this);

        db = helper.getReadableDatabase();

        List<ListItems> items = new ArrayList<ListItems>();
        Cursor c = db.query("tBook", new String[]{"_id", "title", "text"}, null, null, null, null, null, null);

        boolean isEof = c.moveToLast();
        while(isEof) {
            items.add(new ListItems(c.getString(1), c.getString(2)));
            isEof = c.moveToPrevious();
        }

        c.close();
        db.close();

        // アダプタ生成
        ListAdapter adapter = new ListViewAdapter(this, R.layout.row, items);

        // アダプタ設定
        setListAdapter(adapter);

独自アダプターのgetView()にてconvertViewにデータが残っていればそれを再利用し、無い場合はtvResId(=R.layout.row.xml)をインフレートします。

なお、MainActivityのitemsにアイテムを詰める際、最後尾から先頭へカーソルを移動させれば最新のデータが一番上に、先頭から催行日へ移動させれば最新のデータは一番下に表示されます。