【问题标题】: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 回收?

标签: android listview checkbox android-listview getview


【解决方案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。它涵盖了两者。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-04-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多