cómo mostrar contactos en una vista de lista en Android para Android api 11+

Lo siento si esto parece la misma pregunta un millón de veces … pero una búsqueda en Google no proporciona resultados, solo un montón de tutoriales desactualizados que usan managedQuery y otras soluciones en desuso …

Pasé por la capacitación del desarrollador de Android para recuperar una lista de contactos , pero el tutorial está incompleto e incluso la descarga del código de muestra no ayuda porque el código de muestra es para una manipulación más avanzada de la lista de contactos (búsqueda, etc.)

En cualquier caso, no hay ninguna razón por la cual no debería haber una solución simple para esto, así que espero que alguien pueda responder aquí porque estoy seguro de que esto se ha hecho un millón de veces y estoy seguro de que hay docenas de otros desarrolladores de Android iniciales. apreciaría esto

He seguido el tutorial según mi leal saber y entender, sin que aparezcan contactos. Creo que lo más importante es que TO_IDS es una matriz de enteros que apunta a android.R.id.text1 . Estoy confundido de cómo se supone que de alguna manera debe extraer una serie de nombres de contacto.

Además, estoy confundido por qué se necesita una vista de texto cuando el objective final es mostrar una vista de lista … En el tutorial, tenemos mContactsList que es una vista de lista … Pero llenamos la vista de lista con un adaptador que apunta a R.layout.contact_list_item que es solo textviews poblado por TO_IDS, una matriz de enteros.

 mContactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view); mCursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0); mContactList.setAdapter(mCursorAdapter); 

¿Qué estoy haciendo mal y cómo simplemente visualizo la lista de contactos en una vista de lista?

EDITAR: agregando mi código:

en mi clase de fragmento:

 public class MyFragment extends Fragment implements LoaderManager.LoaderCallbacks{ private static final String[] FROM_COLUMNS = {ContactsContract.Contacts.DISPLAY_NAME_PRIMARY }; private static final int[] TO_IDS = {android.R.id.text1}; ListView mContactList; private SimpleCursorAdapter mCursorAdapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ return inflater.inflate(R.layout.contact_list_view,container,false); } @Override public void onActivityCreated(Bundle savedInstanceState){ super.onActivityCreated(savedInstanceState); mContactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view); mCursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.contact_list_item, null, FROM_COLUMNS, TO_IDS, 0); mContactList.setAdapter(mCursorAdapter); } @Override public Loader onCreateLoader(int i, Bundle bundle) { return null; } @Override public void onLoadFinished(Loader cursorLoader, Cursor cursor) { } @Override public void onLoaderReset(Loader cursorLoader) { } } 

en mi activity_main.xml:

    

en mi contact_list_view xml:

   

En mi contact_list_item xml

   

finalmente para contact_list_layout xml:

¿Qué pongo en contact_list_layout.xml ? ¿Es solo un vacío? No está claro en el tutorial cómo se maneja este xml. Dice que este XML es el fragmento, pero si es el fragmento, ¿por qué definimos una lista ya en el contact_list_view.xml ?

Pequeño ejemplo simplificado para mostrar el nombre de los contactos en un ListView . Debajo de Fragment extiende ListFragment que tiene un diseño predeterminado. No necesita especificar el suyo. El diseño de los elementos de la lista también se toma de los diseños predeterminados de Android ( android.R.layout.simple_list_item_1 ) que es una simple línea de texto por elemento.

 import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract.Contacts; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.CursorAdapter; import android.support.v4.widget.SimpleCursorAdapter; public class ContactListFragment extends ListFragment implements LoaderCallbacks { private CursorAdapter mAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // create adapter once Context context = getActivity(); int layout = android.R.layout.simple_list_item_1; Cursor c = null; // there is no cursor yet int flags = 0; // no auto-requery! Loader requeries. mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // each time we are started use our listadapter setListAdapter(mAdapter); // and tell loader manager to start loading getLoaderManager().initLoader(0, null, this); } // columns requested from the database private static final String[] PROJECTION = { Contacts._ID, // _ID is always required Contacts.DISPLAY_NAME_PRIMARY // that's what we want to display }; // and name should be displayed in the text1 textview in item layout private static final String[] FROM = { Contacts.DISPLAY_NAME_PRIMARY }; private static final int[] TO = { android.R.id.text1 }; @Override public Loader onCreateLoader(int id, Bundle args) { // load from the "Contacts table" Uri contentUri = Contacts.CONTENT_URI; // no sub-selection, no sort order, simply every row // projection says we want just the _id and the name column return new CursorLoader(getActivity(), contentUri, PROJECTION, null, null, null); } @Override public void onLoadFinished(Loader loader, Cursor data) { // Once cursor is loaded, give it to adapter mAdapter.swapCursor(data); } @Override public void onLoaderReset(Loader loader) { // on reset take any old cursor away mAdapter.swapCursor(null); } }