I'm trying to use a SimpleCursorAdapter
with a ViewBinder
to get an image from the database and put it into my ListView
item view. Here is my code:
private void setUpViews() {
mNewsView = (ListView) findViewById(R.id.news_list);
Cursor cursor = getNews();
SimpleCursorAdapter curAdapter = new SimpleCursorAdapter(
getApplicationContext(), R.layout.cursor_item, cursor,
new String[] { "title", "content", "image" },
new int[] { R.id.cursor_title, R.id.cursor_content,
R.id.news_image });
ViewBinder viewBinder = new ViewBinder() {
public boolean setViewValue(View view, Cursor cursor,
int columnIndex) {
ImageView image = (ImageView) view;
byte[] byteArr = cursor.getBlob(columnIndex);
image.setImageBitmap(BitmapFactory.decodeByteArray(byteArr, 0, byteArr.length));
return true;
}
};
ImageView image = (ImageView) findViewById(R.id.news_image);
viewBinder.setViewValue(image, cursor, cursor.getColumnIndex("image"));
curAdapter.setViewBinder(viewBinder);
mNewsView.setAdapter(curAdapter);
}
I am getting a :
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 60
while executing byte[] byteArr = cursor.getBlob(columnIndex);
. Does anyone have an idea what am I doing wrong?
I extended SimpleCursorAdapter, and while I did not use a ViewBinder here is my code for using an image stored as a blob in an sqlite database in a listview. This was adapted from an article I read here.
My layout file for a row is:
row_layout_two_line.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/select_item">
<ImageView
android:id="@+id/pic"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
android:contentDescription="@string/imagedesc"
android:src="@drawable/icon"
android:layout_gravity="center_vertical">
</ImageView>
<LinearLayout
android:id="@+id/linearLayout0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="@+id/label"
android:textStyle="bold"
android:textColor="#000"
android:textSize="20sp" >
</TextView>
<TextView
android:id="@+id/label1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="@+id/label1"
android:textStyle="bold"
android:textColor="#000"
android:textSize="20sp" >
</TextView>
</LinearLayout>
<TextView
android:id="@+id/label2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="35dp"
android:text="@+id/label2"
android:textColor="#000"
android:textSize="15sp" >
</TextView>
</LinearLayout>
The calling code
...
adapter = null;
mCursor = search();
startManagingCursor(mCursor);
// Now create a new list adapter bound to the cursor.
BaseAdapter adapter = new ImageCursorAdapter(this, // Context.
R.layout.row_layout_two_line, // Specify the row template
// to use (here, two
// columns bound to the
// two retrieved cursor
// rows).
mCursor, // Pass in the cursor to bind to.
// Array of cursor columns to bind to.
new String [] {"personImage", "firstName", "lastName", "title"},
// Parallel array of which template objects to bind to those
// columns.
new int[] { R.id.pic, R.id.label, R.id.label1, R.id.label2 });
// Bind to our new adapter.
setListAdapter(adapter);
...
ImageCursorAdapter.java
import android.content.Context;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
public class ImageCursorAdapter extends SimpleCursorAdapter {
private Cursor c;
private Context context;
public ImageCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
}
public View getView(int pos, View inView, ViewGroup parent) {
View v = inView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.row_layout_two_line, null);
}
this.c.moveToPosition(pos);
String firstName = this.c.getString(this.c.getColumnIndex("firstName"));
String lastName = this.c.getString(this.c.getColumnIndex("lastName"));
String titleStr = this.c.getString(this.c.getColumnIndex("title"));
byte[] image = this.c.getBlob(this.c.getColumnIndex("personImage"));
ImageView iv = (ImageView) v.findViewById(R.id.pic);
if (image != null) {
// If there is no image in the database "NA" is stored instead of a blob
// test if there more than 3 chars "NA" + a terminating char if more than
// there is an image otherwise load the default
if(image.length > 3)
{
iv.setImageBitmap(BitmapFactory.decodeByteArray(image, 0, image.length));
}
else
{
iv.setImageResource(R.drawable.icon);
}
}
TextView fname = (TextView) v.findViewById(R.id.label);
fname.setText(firstName);
TextView lname = (TextView) v.findViewById(R.id.label1);
lname.setText(lastName);
TextView title = (TextView) v.findViewById(R.id.label2);
title.setText(titleStr);
return(v);
}
}
Here is what it looks like in the end