Android : 列表视图滚动期间未选中复选框

Android : Unchecked CheckBox during List View Scrolling

我有一个 ListView,里面有一个 CheckBox。我点击了一些复选框并仍在滚动 - 完美,直到我决定向后滚动。此时,选中的 CheckBoxes 未选中,其他未选中的 CheckBoxes 已选中。我认为我的代码有一些错误,请帮助我!从现在开始我感谢你!以下代码:

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));
}
 }

我认为问题可能出在您在 CheckBox 点击侦听器中使用的 pos 变量。

假设为位置 0 调用 getView(),然后是位置 1,然后是位置 2,等等(足以用所有可见位置填满列表)。完成后,pos 等于(比方说)10。单击位置 3 的 CheckBox 时会发生什么?我相信你最终会设置 listIsChecked[10] = true.

您应该去掉 pos 变量,只使用传递给 getView()position 参数。如果编译器说它不能在点击侦听器中使用非最终变量,则可以将其设置为 final

@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();
        }
    });

    // ...
}