Изображения в SimpleCursorAdapter - PullRequest
6 голосов
/ 15 июля 2011

Я пытаюсь использовать SimpleCursorAdapter с ViewBinder, чтобы получить изображение из базы данных и поместить его в мой 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);.У кого-нибудь есть идеи, что я делаю не так?

Ответы [ 3 ]

11 голосов
/ 20 августа 2012

Я расширил SimpleCursorAdapter, и хотя я не использовал ViewBinder, здесь мой код для использования изображения, хранящегося в виде большого двоичного объекта в базе данных sqlite в виде списка. Это было адаптировано из статьи, которую я прочитал здесь .

Мой файл макета для строки:

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>

enter image description here

Телефонный код

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

} * * тысяча двадцать-один

Вот как это выглядит в конце

enter image description here

4 голосов
/ 04 февраля 2012

Я думаю, что cursor.moveToFirst() не был вызван, поэтому курсор выбрасывает android.database.CursorIndexOutOfBoundsException.

Перед использованием cursor вы должны всегда проверять, пустой курсор или нет, вызывая cursor.moveToFirst().Это также установит курсор на первую позицию.

2 голосов
/ 08 июня 2016

Список контактов с использованием ListView и SimpleCusrorAdapter с фотографиями контактов и фильтром / поиском

Я искал более простое решение, и мое окончательное решение гораздо ближе к тому, которое Даниил упомянул здесь, поэтомуЯ думал, что я должен поделиться своим здесь.Я использую Фрагмент, чтобы показать контакты устройства в виде списка имен с их изображениями.Результат очень похож на результат Дэниела, но показывает только имена.После того, как вы поймете код, очень легко будет получить дополнительную информацию.

В моем случае я выбирал имена и изображения из ContactsContract с использованием PHOTO_URI, поэтому мне не пришлось расширять SimpleCursorAdapter, как это делал Дэниел.

Мой пример также включает в себя фильтрацию списка контактов по типу пользователя в SearchView для поиска контакта

У меня есть фрагмент с именем FragmentContacts и два файла макета, первый из которых основной макет frag_contacts.xmlи второй для каждой строки контакта 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);
    }
}
...