Christian Giupponi
Christian Giupponi

Reputation: 7618

Android - custom adapter for multiple choice listview

i need to read the contact list in my android app and show it to the user with a multiple choice option. I've just seen the android example with the ListView.CHOICE_MODE_MULTIPLE but i need something different, i want a custm layout. I need to show bot the name and the number of the contact so i created my own adapter. First of all i made myown class to create a Contact:

 //Contacts class   
public class Contatto {


    private String nome; //The name
    private String numero;//number

    public String getNome(){ //Get Name
        return nome;
    }

    public String getNumero(){ //Get number
        return numero;
    }

    public void setNome(String n){ //Set name
        this.nome = n;
    }

    public void setNumero(String n){ //Set number
        this.numero = n;
    }

}

Then i use a cicle to get all the contatcs using a thread to notify the user that the app is working...

import java.util.ArrayList;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class RecuperaRubrica extends ListActivity{


private ProgressDialog m_ProgressDialog = null;
private ArrayList<Contatto> arrayContatti = null;
private ContattoAdapter m_adapter;
private Runnable viewContatti;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.recupera_rubrica);

    arrayContatti = new ArrayList<Contatto>();
    this.m_adapter = new ContattoAdapter(this, R.layout.riga, arrayContatti);
    setListAdapter(this.m_adapter);

    viewContatti = new Runnable(){
        @Override
        public void run() {
            getContatti();
        }
    };
    Thread thread =  new Thread(null, viewContatti, "MagentoBackground");
    thread.start();
    m_ProgressDialog = ProgressDialog.show(RecuperaRubrica.this,    
          "ATTENDI...", "Recupero contatti in corso ...", true);
}
private Runnable returnRes = new Runnable() {

    @Override
    public void run() {
        if(arrayContatti != null && arrayContatti.size() > 0){
            m_adapter.notifyDataSetChanged();
            for(int i=0;i<arrayContatti.size();i++)
            m_adapter.add(arrayContatti.get(i));
        }
        m_ProgressDialog.dismiss();
        m_adapter.notifyDataSetChanged();
    }
};
private void getContatti(){
      try{
          arrayContatti = new ArrayList<Contatto>();
          Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null); //Cursore della rubrica
          while (cursor.moveToNext()) { //Entro nel ciclo se trovo almeno un contatto
              try{
                //Recupero tutte le info dell'utente corrente
              String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); 
              String name=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
              String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));

              //Se è disponibile almeno un numero di telefono lo recupero
              if (Integer.parseInt(hasPhone) > 0) {
                  Cursor phones = getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId, null, null);
                  while (phones.moveToNext()) { 
                      String phoneNumber = phones.getString(phones.getColumnIndex( ContactsContract.CommonDataKinds.Phone.NUMBER));

                      phoneNumber = str_replace("-","",phoneNumber);
                      phoneNumber = str_replace("+39","",phoneNumber);

                      Contatto contatto = new Contatto();
                      contatto.setNome(name.trim());
                      contatto.setNumero(phoneNumber.trim());

                      if(!arrayContatti.contains(contatto)){
                          arrayContatti.add(contatto);
                      }
                  } 
                  phones.close(); //Chiudo la rubrica
              }
          }catch(Exception e){}
         }

        } catch (Exception e) {
          Log.e("BACKGROUND_PROC", e.getMessage());
        }
        runOnUiThread(returnRes);
    }
private class ContattoAdapter extends ArrayAdapter<Contatto> {

    private ArrayList<Contatto> items;

    public ContattoAdapter(Context context, int textViewResourceId, ArrayList<Contatto> items) {
            super(context, textViewResourceId, items);
            this.items = items;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.riga, null);
            }
            Contatto o = items.get(position);
            if (o != null) {
                    TextView tt = (TextView) v.findViewById(R.id.NomeElenco);
                    TextView bt = (TextView) v.findViewById(R.id.NumeroElenco);
                    if (tt != null) {
                          tt.setText(o.getNome());                            
                    }
                    if(bt != null){
                          bt.setText(o.getNumero());
                    }
            }
            return v;
    }
}

public String str_replace (String search, String replace, String subject)
{
  StringBuffer  result = new StringBuffer (subject);
  int  pos = 0;
  while (true)
  {
    pos = result.indexOf (search, pos);
    if (pos != -1)
      result.replace (pos, pos + search.length (), replace);
    else
      break;
  }
  return result.toString ();
}
}

this is the simple xml layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
>
    <ListView 
        android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
      ></ListView>  

</LinearLayout>

this work but when i run the app if i check the first result then scroll the page also the first result in the new page is checked and so on...can you help me to understand why?

Upvotes: 2

Views: 3518

Answers (1)

R.daneel.olivaw
R.daneel.olivaw

Reputation: 2679

I faced a problem like this before myself, below was the reason what I found it to be.

As the list view uses view object recycling to save memory we need to have some sort of mechanism to store the selection state of each list item and then use it in the get view method to check or uncheck(imp) the selection when the view is being retrieved.

I hope it helps

Upvotes: 1

Related Questions