ListView滚动中的复选框问题

时间:2013-09-26 02:27:57

标签: android android-listview

我有listview的文字和复选框。滚动列表视图时,该复选框表现得很奇怪。这似乎是一个回收问题。无论如何,我尝试了一些类似帖子中提出的各种选项,但没有一个适合我。我尝试设置并获得其中一个帖子中建议的标记位置,但运气不好。我在我的活动文件中使用自定义适配器作为列表视图。以下是一些代码片段;  活动类:

lv = (ListView) findViewById(R.id.itemdisplay_listview);
lv.setAdapter(new CustomAdapter(this, itemNames, tableNo));

自定义适配器:

private class CustomAdapter extends BaseAdapter {

        private List<String> mListItems;
        private LayoutInflater mLayoutInflater;
        ViewHolder holder;
        int a = 1;

        public CustomAdapter(Context context, List<String> arrayList,
                String table) {
            tableNumber = table;
            mListItems = arrayList;

            // get the layout inflater
            mLayoutInflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return mListItems.size();
        }

        @Override
        public Object getItem(int position) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return 0;
        }

        private class ViewHolder {

            TextView itemName, quantity;
            CheckBox checkbox;
            ImageButton addBtn, minusBtn;

        }

        @Override
        public View getView(int position, View convertview, ViewGroup viewGroup) {

            // create a ViewHolder reference

            // check to see if the reused view is null or not, if is not null
            // then
            // reuse it
            if (convertview == null) {
                holder = new ViewHolder();

                convertview = mLayoutInflater.inflate(
                        R.layout.itemdisplay_list, null);

                holder.itemName = (TextView) convertview
                        .findViewById(R.id.itemdisplaylist_name);
                holder.addBtn = (ImageButton) convertview
                        .findViewById(R.id.itemdisplaylist_add);
                holder.minusBtn = (ImageButton) convertview
                        .findViewById(R.id.itemdisplaylist_minus);
                holder.quantity = (TextView) convertview
                        .findViewById(R.id.itemdisplaylist_quantity);
                holder.checkbox = (CheckBox) convertview
                        .findViewById(R.id.itemdisplaylist_cbox);

                // holder.checkbox.setTag(position);


                // the setTag is used to store the data within this view
                convertview.setTag(holder);
            } else {
                // the getTag returns the viewHolder object set as a tag to the
                // view
                holder = (ViewHolder) convertview.getTag();
            }

            holder.checkbox.setOnClickListener(checkListener);
            doneBtn.setEnabled(true);

            holder.minusBtn.setImageResource(R.drawable.minus);
            holder.quantity.setText(String.valueOf(a));
            holder.addBtn.setImageResource(R.drawable.add);
            holder.addBtn.setOnClickListener(addBtnClick);
            holder.minusBtn.setOnClickListener(minusBtnClick);

            String stringItem = mListItems.get(position);

            if (stringItem != null) {
                if (holder.itemName != null) {
                    // set the item name on the TextView
                    holder.itemName.setText(stringItem);
                }
            }

            // this method must return the view corresponding to the data at the
            // specified position.
            return convertview;

        }

        private OnClickListener checkListener = new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                /*doneBtn.setOnClickListener(doneBtnClick);*/
                View view = (View) v.getParent();

                CheckBox cb = (CheckBox) view
                        .findViewById(R.id.itemdisplaylist_cbox);
                TextView tv = (TextView) view
                        .findViewById(R.id.itemdisplaylist_name);
                TextView tv1 = (TextView) view
                        .findViewById(R.id.itemdisplaylist_quantity);
                if (cb.isChecked()) {
                    map.put(tv.getText().toString(), tv1.getText().toString());
                } else {
                    for (Iterator<Map.Entry<String, String>> it = map
                            .entrySet().iterator(); it.hasNext();) {

                        Map.Entry<String, String> entry = it.next();
                        String item = entry.getKey();
                        if ((tv.getText().toString()).equals(item)) {
                            it.remove();
                        }
                    }
                }

            }
        };

我已经挣扎了很长时间。请指教。感谢。

5 个答案:

答案 0 :(得分:1)

如果您说 100个CB 的数据,那么您还需要存储他们的checked/unchecked state。假设一个包含100个元素的布尔数组 CheckedStatus [100] 。在GetView中

 if(CheckedStatus[position] == true) {
 // check the check box
 } else {
 // uncheck it 
}.

该位置是GetView函数中收到的位置

答案 1 :(得分:1)

在自定义列表视图适配器中调用 setChecked 后调用 setOnCheckedChangeListener 。这样您就可以切断指向回收视图中的老听众。

答案 2 :(得分:0)

boolean checked变量添加到ViewHolder。在checkListener中更改它。然后在getView添加holder.checkbox.setChecked(holder.checked)

希望它有所帮助。

答案 3 :(得分:0)

您需要使用某种模型对象来保留复选框的状态,然后使用该模型而不是简单的String作为数据结构:

// Oversimplified, but adiquate for our purposes.
public class ItemModel
{
    public String text;
    public boolean isChecked;
}

然后,不是将一个字符串数组传递给适配器,而是传递一个ItemModels数组。 您需要的字符串将是text参数,然后您必须将复选框值设置为isChecked值。

一旦复选框的状态发生变化,剩下的就是更改isChecked值。 在初始化if(convertView == null)参数后,在holder.checkbox块内的getItem方法内执行此操作。另外,请务必在方法参数position中生成final变量。

以下是代码:

holder.checkbox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() 
        {           
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
            {
                mListItems.get(position).isChecked = isChecked;

            }
        });

希望这会有所帮助:)

答案 4 :(得分:0)

我的猜测是你被循环问题所困扰。
我建议你先使用else语句中的以下内容删除监听器

holder.checkbox.setOnCheckedChangeListener(null);

在您的代码中如下:

} else {
                // the getTag returns the viewHolder object set as a tag to the
                // view
                holder = (ViewHolder) convertview.getTag();
                holder.checkbox.setOnCheckedChangeListener(null);
            }