6

我正在尝试使用 aSimpleCursorAdapterViewBinder从数据库中获取图像并将其放入我的ListView项目视图中。这是我的代码:

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);
}

我正进入(状态:

android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 60

在执行时byte[] byteArr = cursor.getBlob(columnIndex);。有谁知道我做错了什么?

4

3 回答 3

11

我扩展了 SimpleCursorAdapter,虽然我没有使用 ViewBinder,但这里是我的代码,用于在列表视图的 sqlite 数据库中使用存储为 blob 的图像。这是改编自我在这里读到的一篇文章。

我的一行布局文件是:

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>

在此处输入图像描述

调用代码

...
    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);
}

}

这是它最终的样子

在此处输入图像描述

于 2012-08-20T16:00:18.400 回答
4

我认为cursor.moveToFirst()尚未调用,所以光标正在抛出android.database.CursorIndexOutOfBoundsException.

在使用之前,cursor您应该始终通过调用来检查光标是否为空cursor.moveToFirst()。这也将光标定位在第一个位置。

于 2012-02-04T16:54:06.080 回答
4

使用 ListView 和 SimpleCusrorAdapter 与联系人照片和过滤器/搜索的联系人列表

我一直在寻找一个更简单的解决方案,我的最终解决方案非常接近 Daniel 在这里提到的那个,所以我想我应该在这里分享我的。我正在使用 Fragment 将设备联系人显示为带有图片的名称列表。结果与 Daniel 的结果非常相似,但只显示名称。了解代码后,可以很容易地显示更多信息。

在我的情况下,我使用 PHOTO_URI 从 ContactsContract 获取姓名和图片,因此我不必SimpleCursorAdapter像 Daniel 那样扩展。

我的示例还包括在用户输入时过滤联系人列表SearchView以查找联系人

我有一个 FragmentFragmentContacts和两个 Layout 文件,第一个是 main Layout frag_contacts.xml,第二个是每个 contact row list_row_contact

frag_contacts.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@android:color/holo_blue_light"
        android:padding="8dip">

        <android.support.v7.widget.SearchView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            android:id="@+id/searchView"/>
    </FrameLayout>
    <LinearLayout
        android:id="@+id/ll_contactList"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="9"
        android:orientation="vertical" >
        <ListView
            android:id="@+id/lv_ContactList"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:divider="#aaaaaa"
            android:dividerHeight="1dp" >
        </ListView>
    </LinearLayout>
</LinearLayout>

list_row_contact.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="wrap_content"
    android:orientation="horizontal"
    android:descendantFocusability="blocksDescendants">

    <FrameLayout
        android:layout_height="match_parent"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:gravity="center">

        <ImageView
            android:id="@+id/imgContact"
            android:layout_width="35dip"
            android:layout_height="35dip"
            android:layout_gravity="center"
            android:layout_margin="5dip" />
    </FrameLayout>

    <TextView
        android:id="@+id/contact_name"
        android:layout_height="match_parent"
        android:layout_width="0dp"
        android:layout_weight="6"
        android:gravity="center_vertical"
        android:textSize="18sp"
        android:paddingLeft="10dip">
    </TextView>
</LinearLayout>

FragmentContacts.java

public class FragmentContacts extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor>{
    private ListView lv_ContactList;
    private SearchView searchView;
    private SimpleCursorAdapter mCursorAdapter;

    private static final String DISPLAY_NAME = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ? Contacts.DISPLAY_NAME_PRIMARY : Contacts.DISPLAY_NAME;

    private static final String[] contactsColumns = {    Contacts._ID, Contacts.LOOKUP_KEY, DISPLAY_NAME, Contacts.PHOTO_URI    };
    private final String contactsFilter = "(" +Contacts.HAS_PHONE_NUMBER+ "='1') AND (" + Contacts.IN_VISIBLE_GROUP + "='1')";
    private final String contactsSortOrder = DISPLAY_NAME + " COLLATE LOCALIZED ASC";

    private final static String[] listDisplayColumns = { DISPLAY_NAME, Contacts.PHOTO_URI   };
    private final static int[] listDataViewIDs = { R.id.contact_name, R.id.imgContact };

    String[] mSelectionArgs;

   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.frag_contacts, null);
        lv_ContactList = (ListView)view.findViewById(R.id.lv_ContactList);
        searchView = (SearchView)view.findViewById( R.id.searchView);
        return view;
    }

    @Override
    public void onResume(){
        super.onResume();

        mCursorAdapter= new SimpleCursorAdapter( getActivity(), R.layout.list_row_contact, null, listDisplayColumns, listDataViewIDs, 0);
        lv_ContactList.setAdapter(mCursorAdapter);
        getLoaderManager().initLoader(0, null, this);
        searchView.setOnQueryTextListener( new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit( String query ) {return false;}
            @Override
            public boolean onQueryTextChange( String newText ) {
                if( newText.isEmpty() ) mSelectionArgs = null;
                else mSelectionArgs = new String[]{ "%"+newText.trim()+"%"};
                getLoaderManager().restartLoader( 0, null, FragmentContacts.this );
                return false;
            }
        } );
    }

    @Override
    public Loader<Cursor> onCreateLoader( int id, Bundle args ) {
        if(mSelectionArgs == null)
            return new CursorLoader( getActivity(), Contacts.CONTENT_URI, contactsColumns, contactsFilter, null, contactsSortOrder );
        else
            return new CursorLoader( getActivity(), Contacts.CONTENT_URI, contactsColumns, contactsFilter + " AND (" + DISPLAY_NAME+" LIKE ?)", mSelectionArgs, contactsSortOrder );
    }
    @Override
    public void onLoadFinished( Loader<Cursor> loader, Cursor data ) {
        mCursorAdapter.swapCursor(data);
    }
    @Override
    public void onLoaderReset( Loader<Cursor> loader ) {
        mCursorAdapter.swapCursor(null);
    }
}
于 2016-06-08T18:28:36.053 回答