I’ve been writing a bit more Android code, and came upon the need to write a custom CursorAdapter for a ListView, as the way I wanted to display data from a Cursor was dependent on relationships between different fields of the database.
Of the problems I encountered, the most obvious was when I tried to inflate views using View.inflate(), and found I would get the following error:
UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView at android.widget.AdapterView |
After a bit of rummaging around, I found that the following bit of code would work when attached to a ListView using setAdapter().
public class ExampleCursorAdapter extends CursorAdapter { public ExampleCursorAdapter(Context context, Cursor c) { super(context, c); } @Override public void bindView(View view, Context context, Cursor cursor) { TextView summary = (TextView)view.findViewById(R.id.summary); summary.setText(cursor.getString( cursor.getColumnIndex(ExampleDB.KEY_EXAMPLE_SUMMARY))); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(R.layout.item, parent, false); bindView(v, context, cursor); return v; } } |
The above example code doesn’t actually require a CursorAdapter, it would easily be implemented using a SimpleCursorAdapter, but it serves to show the idea. Basicly, get a LayoutInflater from the context, and use the version of inflate() that does not attach to the root view.
Thanks a lot !
I was so annoyed trying to figure out how to implement a CursorAdapter 😉
Why do you call bindView() in newView()? It seems to then be called twice, at least on the emulator.
Don’t see much info on CursorAdapter. Thanks for the info.
suggestions:
1. Move “LayoutInflater inflater = LayoutInflater.from(context);” to construction to avoid execute it every time.
2. Calling bindView() from newView() is not necessary. bindView() will be called after newView() by the framework.
A custom CursorAdapter from one of my projects:
protected class ActivityCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private int mActivityIndex;
private int mTimeIndex;
private int mActionIndex;
private int mAmountIndex;
public ActivityCursorAdapter(Context context, Cursor c) {
super(context, c);
mActivityIndex = c.getColumnIndex(Notes.ACTIVITY);
mTimeIndex = c.getColumnIndex(Notes.TIME);
mActionIndex = c.getColumnIndex(Notes.ACTION);
mAmountIndex = c.getColumnIndex(Notes.AMOUNT);
mInflater = LayoutInflater.from(context);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView activity = (TextView) view.findViewById(android.R.id.text1);
TextView time = (TextView) view.findViewById(android.R.id.text2);
TextView actionAndAmount = (TextView) view.findViewById(R.id.text3);
activity.setText(cursor.getString(mActivityIndex));
long lTime = cursor.getLong(mTimeIndex);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(lTime);
time.setText(cal.get(Calendar.HOUR_OF_DAY) + “:” + String.format(“%02d”, cal.get(Calendar.MINUTE)));
String amount = cursor.getString(mAmountIndex);
if ( amount.length() > 0){
actionAndAmount.setText(cursor.getString(mActionIndex) + ” (” + amount + “)”);
} else {
actionAndAmount.setText(cursor.getString(mActionIndex));
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.activityitem_list, null);
}
}