how do i create a custom cursor adapter for a listview for use with images and text?
Will,
I've actually implemented something incredibly similar to what you are looking for. Here is my implementation.
import android.content.Context;import android.content.SharedPreferences;import android.content.res.Resources;import android.database.Cursor;import android.preference.PreferenceManager;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.CursorAdapter;import android.widget.ImageView;import android.widget.TextView;public class ItemAdapter extends CursorAdapter { private LayoutInflater mLayoutInflater; private Context mContext; public ItemAdapter(Context context, Cursor c) { super(context, c); mContext = context; mLayoutInflater = LayoutInflater.from(context); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View v = mLayoutInflater.inflate(R.layout.items_row, parent, false); return v; } /** * @author will * * @param v * The view in which the elements we set up here will be displayed. * * @param context * The running context where this ListView adapter will be active. * * @param c * The Cursor containing the query results we will display. */ @Override public void bindView(View v, Context context, Cursor c) { String title = c.getString(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_TITLE)); String date = c.getString(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_DATE)); String imagePath = c.getString(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_IMG)); int deletion = c.getInt(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_DELETION)); int priority = c.getInt(c.getColumnIndexOrThrow(ItemDbAdapter.KEY_PRIORITY)); /** * Next set the title of the entry. */ TextView title_text = (TextView) v.findViewById(R.id.item_text); if (title_text != null) { title_text.setText(title); } /** * Set Date */ TextView date_text = (TextView) v.findViewById(R.id.item_date); if (date_text != null) { date_text.setText(date); } /** * Decide if we should display the paper clip icon denoting image attachment */ ImageView item_image = (ImageView) v.findViewById(R.id.item_attachment); item_image.setVisibility(ImageView.INVISIBLE); if (imagePath != null && imagePath.length() != 0 && item_image != null) { item_image.setVisibility(ImageView.VISIBLE); } /** * Decide if we should display the deletion indicator */ ImageView del_image = (ImageView) v.findViewById(R.id.item_deletion); del_image.setVisibility(ImageView.INVISIBLE); if (deletion == 1) { del_image.setVisibility(ImageView.VISIBLE); } }}
XML just incase...
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="@drawable/list_bg"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/item_text" android:layout_width="200dp" android:layout_height="wrap_content" android:lines="1" android:scrollHorizontally="true" android:ellipsize="end" android:paddingLeft="2sp" android:paddingTop="2sp" android:textSize="18sp" android:textStyle="bold" android:shadowColor="#90909090" android:shadowDx="1.0" android:shadowDy="1.0" android:shadowRadius="1.0"/> <TextView android:id="@+id/item_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12sp" android:textColor="#FF808080" android:paddingLeft="2sp" android:paddingTop="2sp"/> </LinearLayout> <ImageView android:id="@+id/item_deletion" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/deletion" android:visibility="invisible" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:paddingRight="5sp"/> <ImageView android:id="@+id/item_attachment" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/attachment" android:visibility="invisible" android:layout_centerVertical="true" android:layout_toLeftOf="@id/item_deletion"/></RelativeLayout>
This displays two rows of text and up to 2 images to the right of the text depending on certain conditions.
I hope this can give you a basis to work from!
Good luck :]
Check what I have done:BTW: CheckpointsView.getImageResId()
returns a valid drawable reference
public class CheckpointCursorAdapter extends ResourceCursorAdapter { private int layoutType = 0; public static final int BLOTTER = 1; public static final int DAY = 2; public static final int MONTH = 3; public static final int OVERVIEW = 4; public static final int LAYOUT_ID = R.layout.checkpoint_row; public CheckpointCursorAdapter(Context context, int layoutType, Cursor cursor) { super(context, LAYOUT_ID, cursor); this.layoutType = layoutType; } @Override public View newView(Context context, Cursor cur, ViewGroup parent) { LayoutInflater li = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); return li.inflate(LAYOUT_ID, parent, false); } @Override public void bindView(View view, Context context, Cursor cursor) { TextView tvListText = (TextView) view.findViewById(R.id.txtCheckPoint); Date dt = new Date(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.KEY_CHECKPOINT))); switch (layoutType) { case BLOTTER: tvListText.setText(dt.toLocaleString()); ((ImageView) view.findViewById(R.id.imgCheckpointInOut)) .setImageResource(CheckpointsView.getImageResId(cursor.getCount() - cursor.getPosition())); break; case DAY: tvListText.setText(new SimpleDateFormat("HH:mm:ss").format(dt)); ((ImageView) view.findViewById(R.id.imgCheckpointInOut)) .setImageResource(CheckpointsView.getImageResId(cursor.getPosition() + 1)); break; case MONTH: tvListText.setText(new SimpleDateFormat("MMM dd HH:mm:ss").format(dt)); ((ImageView) view.findViewById(R.id.imgCheckpointInOut)) .setImageResource(CheckpointsView.getImageResId(cursor.getPosition() + 1)); break; case OVERVIEW: break; } }}
And the XML just in case
<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/txtCheckPoint" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:padding="8dp" android:textStyle="bold"></TextView><LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="right" android:layout_weight="1" android:layout_marginRight="8px"> <TextView android:id="@+id/txtTotalHours" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20dp" android:padding="8dp" android:paddingRight="12dp"></TextView> <TextView android:id="@+id/txtHourBalanceRow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12dp" android:padding="8dp"> </TextView> <ImageView android:id="@+id/imgCheckpointInOut" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/black_clock" /></LinearLayout>
You can check the whole code at:http://code.google.com/p/droidtimesheet/
Adding images and text is not specific to CursorAdapter
; you use the same technique for any kind of adapter. You can create a layout for your row and inflate it inside your getView
method. The APIDemos sample project, contained in the Android SDK android-sdk-PLATFORM/samples/android-XY/ApiDemos
folder, does what you want. You can find the row definitons in list_item_icon_text.xml
. Here is copy of file content (w/o the license).
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/icon" android:layout_width="48dip" android:layout_height="48dip" /> <TextView android:id="@+id/text" android:layout_gravity="center_vertical" android:layout_width="0dip" android:layout_weight="1.0" android:layout_height="wrap_content" /></LinearLayout>