Android : Unchecked CheckBox during List View Scrolling

I have a ListView with a CheckBox inside its. I had clicked some CheckBoxes and still scrolling - perfect, UNTIL I decided to Scroll back. At this time, the selected CheckBoxes aren't checked and others the wasn't checked had selected. I think that there are some bug at my code, please help me! From now I thank you! Following the code:

public class TableListAdapter extends
ArrayAdapter<String>
{
    private Context context;
    private int layoutId;
    private String[] numbers;
    private int btnColorId;
    public boolean[] listIsChecked;
    char activityOperation;


    int pos;

    public TableListAdapter(Context context, int layoutId, 
     String[] numbers, int btnColorId, char activityOperation)
    {
        super(context, layoutId, numbers);
        this.context = context;
        this.layoutId = layoutId;
        this.numbers = numbers;
        this.btnColorId = btnColorId;
        this.activityOperation = activityOperation;

        listIsChecked = new boolean[numbers.length];
    }

    @Override
    public View getView(int position, View view, ViewGroup parent)
    {
        Holder holder;
        pos = position;

        if (view == null)
        {
            holder = new Holder();
            view = LayoutInflater.from(context).inflate(layoutId, null);

            holder.image = (ImageView) view.findViewById(R.id.practice_list_itemImageView);
            holder.button = (Button) view.findViewById(R.id.practice_list_itemButton);
            holder.checkbox = (CheckBox) view.findViewById(R.id.practice_list_itemCheckBox);
        view.setTag(holder);
        }
        else
        {
            holder = (Holder) view.getTag();
        }


                holder.image.setImageResource(R.drawable.ic_launcher);
        holder.button.setText(numbers[position]);
            holder.button.setBackgroundResource(btnColorId);

              holder.checkbox.setChecked(listIsChecked[position]);

     holder.checkbox.setOnClickListener(new CheckBox.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            listIsChecked[pos] = ((CheckBox)v).isChecked();
        }
    });

    holder.button.setOnClickListener(new Button.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            Intent intent = new Intent(context, ShowTableActivity.class);
            intent.putExtra("activityOperation", activityOperation);
            intent.putExtra("number", pos);
            context.startActivity(intent);
        }
    });

    return view;
}

class Holder
{
    ImageView image;
    Button button;
    CheckBox checkbox;
}
}









<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/practice_list_item_auxiliar"
android:gravity="center">

<Button
    android:id="@+id/practice_list_itemButton"
    android:textSize="@dimen/main_button_text"
    android:textStyle="bold"
    android:layout_width="0dp"
    android:layout_height="70dp"
    android:layout_weight="3"
    android:textColor="@android:color/white"
    android:padding="@dimen/main_button_padding"/>

<ImageView
    android:id="@+id/practice_list_itemImageView"
    android:layout_width="0dp"
    android:layout_weight="1"
    android:layout_height="wrap_content"/>

<LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:orientation="vertical"
    android:gravity="center">
    <CheckBox
        android:id="@+id/practice_list_itemCheckBox"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>







 public class MainPracticeActivity  extends Activity
 {
String[] nums = {"1","2","3","4","5","6","7", "8", "9", "10"};
ListView lv;
char activityOperation;

ImageButton imageButtonLinkeable;
ImageButton imageButtonChoiceable;
ImageButton imageButtonTypeable;
ImageButton buttons[] = new ImageButton[3];

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_practice);

    activityOperation = getIntent().getCharExtra("activityOperation", '0');

    lv = (ListView) findViewById(R.id.main_practice_ListView);
    TableListAdapter tbl = new TableListAdapter
    (this, R.layout.practice_list_item, nums, getMainColor(activityOperation), activityOperation);
    lv.setAdapter(tbl);

    imageButtonLinkeable = (ImageButton)findViewById(R.id.main_practice_imagebutton_linkable);
    imageButtonChoiceable = (ImageButton)
            findViewById(R.id.main_practice_imagebutton_choiceable);
    imageButtonTypeable = (ImageButton)
            findViewById(R.id.main_practice_imagebutton_typeable);
    buttons[0] = imageButtonLinkeable;
    buttons[1] = imageButtonChoiceable;
    buttons[2] = imageButtonTypeable;

    //Set the default drawable resources to the game's buttons
    unselectButtons(buttons);

    //ImageButtons
    imageButtonLinkeable.setOnClickListener(new ImageButton.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            unselectButtons(buttons);
            selectButton(v);
        }
    });

    imageButtonChoiceable.setOnClickListener(new ImageButton.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            unselectButtons(buttons);
            selectButton(v);
        }
    });

    imageButtonTypeable.setOnClickListener(new ImageButton.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            unselectButtons(buttons);
            selectButton(v);
        }
    });
}

private int getMainColor(char activityOperation)
{
    int colorId = -1;

    switch(activityOperation)
    {
        case '+':
            colorId = R.color.add;
            break;

        case '-':
            colorId = R.color.subtract;
            break;

        case '*':
            colorId = R.color.multiply;
            break;

        case '/':
            colorId = R.color.divide;
            break;
    }
    return colorId;
}

private int getSelectedBackground(char activityOperation)
{
    int backgroundId = -1;

    switch(activityOperation)
    {
        case '+':
            backgroundId = R.drawable.circle_button_add_selected;
            break;

        case '-':
            backgroundId = R.drawable.circle_button_subtract_selected;
            break;

        case '*':
            backgroundId = R.drawable.circle_button_multiply_selected;
            break;

        case '/':
            backgroundId = R.drawable.circle_button_divide_selected;
            break;
    }
    return backgroundId;
}

private int getDefaultBackground(char activityOperation)
{
    int backgroundId = -1;

    switch(activityOperation)
    {
        case '+':
            backgroundId = R.drawable.circle_button_add_default;
            break;

        case '-':
            backgroundId = R.drawable.circle_button_subtract_default;
            break;

        case '*':
            backgroundId = R.drawable.circle_button_multiply_default;
            break;

        case '/':
            backgroundId = R.drawable.circle_button_divide_default;
            break;
    }
    return backgroundId;
}

private void unselectButtons(View...buttons)
{
    for(View cb : buttons)
    {
        ((ImageButton)cb).setBackgroundResource(getDefaultBackground(
        activityOperation));
    }
}

private void selectButton(View button)
{
    ((ImageButton)button).setBackgroundResource
    (getSelectedBackground(activityOperation));
}
 }

Upvotes: 0

Views: 46

Answers (1)

Ben P.
Ben P.

Reputation: 54204

I think the problem might be the pos variable you're using inside your CheckBox click listener.

Imagine that getView() is called for position 0, then position 1, then position 2, etc (enough to fill up the list with all the visible positions). Once that's done, pos is equal to (let's say) 10. What happens when you click the CheckBox at position 3? I believe you will wind up setting listIsChecked[10] = true.

You should get rid of the pos variable and just use the position argument passed to getView(). You can make it be final if the compiler says it can't use a non-final variable in the click listener.

@Override
public View getView(final int position, View view, ViewGroup parent)
{
    // ...

    holder.checkbox.setOnClickListener(new CheckBox.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            listIsChecked[position] = ((CheckBox)v).isChecked();
        }
    });

    // ...
}

Upvotes: 1

Related Questions