列表视图项目的不可预测的行为复选框单击
Posted
技术标签:
【中文标题】列表视图项目的不可预测的行为复选框单击【英文标题】:unpredictable behahviour of list view item's checkbox click 【发布时间】:2015-10-04 02:13:49 【问题描述】:在列表视图中我在使用checkboxes
要选择列表列表项时,当checkbox
是listview
项目的背景应该改变,但是当我点击checkbox
的第一个项目时,它的背景变化但是当我向下滚动列表项 3 的背景时,checkbox
状态也会发生变化。我不明白为什么会发生这种情况可能是由于 listview 的回收过程。
public View getView(final int position, View convertView, ViewGroup parent)
TextView tvTitle, tvCat, tvDate;
CheckBox cbAddSummary, cbAddPhoto,cbItemSelect;
Log.i("mponeList:position",String.valueOf(position));
if (convertView == null)
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_mp_one,parent,false);
tvTitle = (TextView)convertView.findViewById(R.id.tv_title);
tvCat = (TextView) convertView.findViewById(R.id.tv_cat);
tvDate = (TextView)convertView.findViewById(R.id.tv_date);
cbAddSummary = (CheckBox) convertView.findViewById(R.id.cb_add_summary);
cbAddPhoto = (CheckBox) convertView.findViewById(R.id.cb_add_photo);
cbItemSelect = (CheckBox) convertView.findViewById(R.id.cb_item_select);
tvTitle = (TextView)convertView.findViewById(R.id.tv_title);
tvCat = (TextView) convertView.findViewById(R.id.tv_cat);
tvDate = (TextView)convertView.findViewById(R.id.tv_date);
cbAddSummary = (CheckBox) convertView.findViewById(R.id.cb_add_summary);
cbAddPhoto = (CheckBox) convertView.findViewById(R.id.cb_add_photo);
cbItemSelect = (CheckBox) convertView.findViewById(R.id.cb_item_select);
cbItemSelect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
View row = ((View) buttonView.getParent());
if (isChecked)
row.setBackgroundResource(R.drawable.shape_mp_list_item_check);
else
row.setBackgroundResource(R.drawable.shape_mm_er_list);
);
MpOneListModel model = this.list.get(position);
tvTitle.setText(model.getTitle());
tvCat.setText(model.getCat());
tvDate.setText(model.getDate());
return convertView;
这是我在适配器的getview
中使用的代码。
【问题讨论】:
是的,这正是因为每当你滚动时都会循环到 Listview ..... @koutuk 如何避免这种情况 这是由于回收到 Listview - 如何避免 --> 通过阅读 ListView 回收? 【参考方案1】:尝试在您的适配器中添加这两种方法
@Override
public int getViewTypeCount()
return list.size() + 1;
@Override
public int getItemViewType(int position)
return position;
【讨论】:
【参考方案2】:您应该在您的模型 (MpOneListModel) 中保持选中状态。更新模型 onCheckedChanged
cbItemSelect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
View row = ((View) buttonView.getParent());
if (isChecked)
model.setChecked(true)
else
model.setChecked(false)
);
然后添加你的逻辑
if(model.isChecked())
//update background
else
//reverse background
当前当您向下滚动时。 您之前的视图正在根据列表视图回收再次使用。所以你最好把你的状态保存在模型本身中
【讨论】:
【参考方案3】:在模型中添加 isChecked 布尔属性并使用 false 初始化它并使用以下代码:
public View getView(final int position, View convertView, ViewGroup parent)
TextView tvTitle, tvCat, tvDate;
CheckBox cbAddSummary, cbAddPhoto,cbItemSelect;
Log.i("mponeList:position",String.valueOf(position));
if (convertView == null)
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_mp_one,parent,false);
tvTitle = (TextView)convertView.findViewById(R.id.tv_title);
tvCat = (TextView) convertView.findViewById(R.id.tv_cat);
tvDate = (TextView)convertView.findViewById(R.id.tv_date);
cbAddSummary = (CheckBox) convertView.findViewById(R.id.cb_add_summary);
cbAddPhoto = (CheckBox) convertView.findViewById(R.id.cb_add_photo);
cbItemSelect = (CheckBox) convertView.findViewById(R.id.cb_item_select);
tvTitle = (TextView)convertView.findViewById(R.id.tv_title);
tvCat = (TextView) convertView.findViewById(R.id.tv_cat);
tvDate = (TextView)convertView.findViewById(R.id.tv_date);
cbAddSummary = (CheckBox) convertView.findViewById(R.id.cb_add_summary);
cbAddPhoto = (CheckBox) convertView.findViewById(R.id.cb_add_photo);
cbItemSelect = (CheckBox) convertView.findViewById(R.id.cb_item_select);
final MpOneListModel model = this.list.get(position);
tvTitle.setText(model.getTitle());
tvCat.setText(model.getCat());
tvDate.setText(model.getDate());
cbItemSelect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
View row = ((View) buttonView.getParent());
model.isChecked = isChecked;
if (isChecked)
row.setBackgroundResource(R.drawable.shape_mp_list_item_check);
else
row.setBackgroundResource(R.drawable.shape_mm_er_list);
);
if(model.isChecked)
cbItemSelect.setCheck(true);
return convertView;
【讨论】:
【参考方案4】:不要忘记列表视图会重复使用您的视图。在 getView 方法中,您应该检查当前项目是否已检查。执行此操作的变体之一 - 在适配器中,您可以添加 ArrayList 并添加已检查的元素。这是示例
MyAdapter extends BaseAdapter
private List<Model> list;
private ArrayList<> selectedList;
public MyAdapter(List<Model> items)
this.list = items;
selectedList = new ArrayList(items.size);
getView(...)
...init view here
final Model item = list.get(position);
checkBox.setChecked(selectedList.contains(item));
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
if (isChecked) selectedList.add(item);
else selectedList.remove(item);
);
【讨论】:
【参考方案5】:您需要在 onCheckedChanged() 方法中保持列表项的位置。也使用 ViewHolder 模式。请参阅this。它涵盖了两者。
【讨论】:
以上是关于列表视图项目的不可预测的行为复选框单击的主要内容,如果未能解决你的问题,请参考以下文章