列表视图项目的不可预测的行为复选框单击

Posted

技术标签:

【中文标题】列表视图项目的不可预测的行为复选框单击【英文标题】:unpredictable behahviour of list view item's checkbox click 【发布时间】:2015-10-04 02:13:49 【问题描述】:

在列表视图中我在使用checkboxes要选择列表列表项时,当checkboxlistview项目的背景应该改变,但是当我点击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。它涵盖了两者。

【讨论】:

以上是关于列表视图项目的不可预测的行为复选框单击的主要内容,如果未能解决你的问题,请参考以下文章

如何使可扩展列表视图的项目选中/不可选中

如何使用uwp中的全选复选框创建带有复选框项目的列表视图

自定义列表单击复选框

“对话框”内的列表视图中的复选框无法正常工作

反应本机列表视图

如何使整行列表视图可点击?