1

I have a ListView that is filled by a CustomAdapter with a specific Layout.
An ArrayList is passed as a parameter to this CustomAdapter, which contains the data for each ListView element.
Each ListView element is composed by a TextView (where I display the data from the ArrayList) and a CheckBox at the right of it.

The data in the ArrayList is correct. This data is also correctly shown when the ListView is filled and it's not repeated in any element (see images below for details).

The issue: When the ListView is filled and displayed on the screen and when I check one of the CheckBoxes, another CheckBox is also checked below every 10th element (see images below for details).

1st element checked 10th element checked

2nd element checked 11th element checked

Last element checked 3rd element checked

In these images you can see, when I check the 1st element, the 10th element is also checked. When I check the 2nd element, the 11th element is also checked too!!!
Even if I check the last element, the 3rd element is checked.

Why is this behavior happening???

Here is the code for the CustomAdapter ElementContentAdapter.java:

@SuppressWarnings("rawtypes")
public class ElementContentAdapter extends BaseAdapter implements OnClickListener {

private final Activity activity;
private final ArrayList elements;
private static LayoutInflater layoutInflater = null;


public ElementContentAdapter(Activity activity, ArrayList data) {
    this.activity = activity;
    this.elements = data;

    layoutInflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public static class ViewHolder {
    public TextView tviContent;
}

@Override
public int getCount() {
    if (elements.size() <= 0) return 1;
    return elements.size();
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public Object getItem(int position) {
    return position;
}

@Override
public void onClick(View view) {
    //
}

@SuppressLint("InflateParams")
public View getView(int position, View convertView, ViewGroup parent) {

    final ViewHolder viewHolder;

    if (convertView== null) {
        convertView = layoutInflater.inflate(R.layout.element_content_checklist, null);

        viewHolder = new ViewHolder();
        viewHolder.tviContent = (TextView) convertView.findViewById(R.id.tvi_content_element_content_checklist);

        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    if (elements.size() <= 0) {
        /**
         * 
         */
    } else if(elements.size() > 0) {
        ElementContent currentElement = null;
        currentElement = (ElementContent) elements.get(position);

        viewHolder.tviContent.setText(currentElement.getContent());

        convertView.setOnClickListener(new ElementContentOnClickListener(position));
    }

    return convertView;
}

private class ElementContentOnClickListener implements OnClickListener {

    private int selectedPosition;

    ElementContentOnClickListener (int position) {
        selectedPosition = position;
    }

    @Override
    public void onClick(View view) {
        CatMenusActivity catMenusActivity = (CatMenusActivity) activity;
        catMenusActivity.elementoContentOnClick(selectedPosition);
    }

}
}

Here is the code for the Layout that is inflated element_content_checklist.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/White"
    android:paddingBottom="10dp"
    android:paddingRight="6dp"
    android:paddingTop="10dp" >

    <TextView
        android:id="@+id/tvi_content_element_content_checklist"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_marginRight="10dp"
        android:layout_toLeftOf="@+id/cbo_mark_element_content_checklist"
        android:gravity="left"
        android:text="@string/txt_content_element_content"
        android:textAllCaps="false"
        android:textColor="@color/DimGray"
        android:textSize="14sp"
        android:textStyle="normal" />

    <CheckBox
        android:id="@+id/cbo_mark_element_content_checklist"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:button="@drawable/content_bg_checkbox_content"
        android:checked="false" />

</RelativeLayout>

The class ElementContent is just a custom class for managing my information, wich is retrieved correctly from a database. It contains the attributes: elementId, contentId and content, with its respective constructor, getters and setters.

Hope I get fully understood for what is happening and what I want to achieve.

Many thanks in advance!

Ayuchuco
  • 79
  • 1
  • 13
  • 2
    That's row recycling for you. You'll have to make the checkbox part of the view holder and then check it based on a flag, either maintained separately for every index, or as part of your `ElementContent`. Tapping the checkbox should change this flag, not just the view. – MH. Sep 27 '14 at 23:35

1 Answers1

2

Add Checkbox to your View Holder and define it getView() method. Then try Using SparseBooleanArray in which you can set it to true when item clicked and can check while refreshing view to update.

SparseBooleanArray pba=new SparseBooleanArray();//this should be global
private class ElementContentOnClickListener implements OnClickListener {

    private int selectedPosition;

    ElementContentOnClickListener (int position) {
        selectedPosition = position;
        pba[position]=true;

    }

    @Override
    public void onClick(View view) {
        CatMenusActivity catMenusActivity = (CatMenusActivity) activity;
        catMenusActivity.elementoContentOnClick(selectedPosition);
    }

}

then in your getView() Method..manually check for selected positions and update checkbox accordingly

holder.checkBox.setChecked(pba[position]); // inside getView()
Rajan Kali
  • 12,627
  • 3
  • 25
  • 37
  • Yes!!! This is solution worked for me like a charm!!! But you have a mistake: It is not 'ParseBooleanArray', is `SparseBooleanArray` (edit your answer). In the constructor of `ElementContentAdapter` I initialized the boolean array with the same size of my elements array. Then, I created a `OnCheckedChangeListener` and assigned it to the ViewHolder's CheckBox for changing the boolean value in the boolean array in the correct position. Finally, in the `getView()` method I read this changed value from the boolean array and assigned to the CheckBox with `setChecked()` method and voila!! – Ayuchuco Oct 16 '14 at 23:05
  • Yep sorry..its SparseBooleanArray :) – Rajan Kali Oct 18 '14 at 03:23