Contact List using ListView and SimpleCusrorAdapter with Contact Photos and Filter/Search
I had been looking for a simpler solution and my final solution is quite closer to the one Daniel mentioned here so I thought I should share mine here. I am using Fragment to show Device Contacts as a list of names with their pictures. Result is pretty similar to that of Daniel's but is showing only names. More information can be shown very easily once you understand the code.
In my case I was fetching names and pictures from ContactsContract using PHOTO_URI so I didn't have to extend SimpleCursorAdapter
as Daniel had to.
My example also includes filtering the list of contacts as user types in SearchView
to find a contact
I have a Fragment called FragmentContacts
and two Layout files, first the main Layout frag_contacts.xml
and second for each 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);
}
}