1

I am not sure if its just me or something else is wrong in my code. I am populating all the phone contacts in a custom listview and all is fine until its populated. The custom listview has a checkbox so that multiple items can be selected. The problem is when I have say 30 contacts loaded in the listview and I select the first contact and I scroll down I see that 11th and 21st contact is also selected. I am not sure why this is happening any information in this unusual issue would be helpful.

Here's the xml code

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent" 
android:layout_height="match_parent">
    <ListView android:id="@android:id/list"
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:drawSelectorOnTop="false"   
        android:choiceMode="multipleChoice"/>
    <TextView android:id="@+id/empty"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content"
        android:text="@string/main_no_contacts"
        android:textColor="@color/white"/>
    </LinearLayout>

The custom layout is

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/rlContactListRowMain" 
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent"
            android:padding="5dp">
<ImageView  android:id="@+id/ivContactIconRow" 
            android:src="@drawable/droid_small" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content"/>
<RelativeLayout android:id="@+id/rlContactListRowChild"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/ivContactIconRow" 
                android:layout_alignTop="@+id/ivContactIconRow">
                <TextView   android:text="Vikram Ramanathan"
                            android:layout_width="wrap_content" 
                            android:layout_height="wrap_content" 
                            android:id="@+id/tvRowContactName" 
                            android:paddingLeft="10dip"
                            android:textColor="@color/white"/>
                <TextView   android:text="Phone Numbers: " 
                            android:layout_width="wrap_content" 
                            android:layout_height="wrap_content" 
                            android:paddingLeft="10dip" 
                            android:id="@+id/tvRowContactPhone"
                            android:layout_below="@+id/tvRowContactName"
                            android:textColor="@color/white"/>                                                                                                                                  
</RelativeLayout>
<CheckBox   android:id="@+id/chkSelectContact" 
            android:layout_height="wrap_content" 
            android:text="" 
            android:layout_width="wrap_content" 
            android:layout_alignParentRight="true"></CheckBox>                          
    </RelativeLayout>

The java code is

    super.onCreate(savedInstanceState);
    setContentView(R.layout.listcontacts);
    phoneContactList = new ArrayList<PhoneContactInfo>();
    this.m_adapter = new PhoneContactListAdapter(this, R.layout.listcontacts_row, phoneContactList);
    setListAdapter(this.m_adapter);

The adapter code is

View v = convertView;
    if (v == null) 
    {
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.listcontacts_row, null);
    }

    PhoneContactInfo phoneContactInfo = phoneContacts.get(position);

    if (phoneContactInfo != null) 
    {
        TextView tvContactName = (TextView) v.findViewById(R.id.tvRowContactName);

        if (tvContactName != null)
        {
            tvContactName.setText(phoneContactInfo.getContactName());
        }

        TextView tvContactNumber = (TextView) v.findViewById(R.id.tvRowContactPhone);

        if (tvContactNumber != null)
        {
            tvContactNumber.setText(phoneContactInfo.getContactNumber());   
        }
    }
    v.setTag(phoneContactInfo);
    phoneContactInfo = null;
    return v;
vikramjb
  • 1,365
  • 3
  • 25
  • 50

2 Answers2

1

I think the problem is that when you populate items you update TextViews and you don't update CheckBox. Your layout for list item is reused and that's why the next item has CheckBox checked. Try saving CheckBox state for every in a list or in your custom class and save it or load it from there.

  • Thank You Mightier, you were correct, the state is not being saved. I have a workaround here (http://stackoverflow.com/questions/4803756/android-cursoradapter-listview-and-checkbox) but the last code that's given where the state is loaded dynamically, there instances two checkboxes. I am not sure when i am supposed to have the second checkbox. In the same layout right ? – vikramjb Sep 01 '11 at 13:01
  • Don't really see two checkboxes there. There is one ArrayList which keeps CheckBox status for every item in ListView. –  Sep 01 '11 at 13:28
  • yeap I was looking at wrong. It worked perfectly. Thank You Mightier. Appreciate your answer :) – vikramjb Sep 02 '11 at 02:38
1

I think Mighter is right. You could confirm this quickly by removing the if (v == null) check and just recreating the view from scratch each time. When you use the recycled view, you will (i.e. convertView) you should make sure to reset all of the Views within as appropriate.

Depending on the level of performance of this list, you may also want to use the ViewHolder pattern and not call findViewById on each call to getView(). I recommend this talk from Google I/O 2010, which goes into some good detail on ListViews and adapters: http://www.youtube.com/watch?v=wDBM6wVEO70

jordanti
  • 156
  • 5
  • Mightier is right, its reusing. When I removed the condition it was resetting whenever I scrolled. +1 for the video. – vikramjb Sep 01 '11 at 12:59