When scrolling custom ListView, the checkbox value changes

前端 未结 8 1941
不思量自难忘°
不思量自难忘° 2020-12-05 07:30


What I have: a custom listview with Textviews and checkbox.


Problem: Suppose my screen can show only 6 items of list at time, and
相关标签:
8条回答
  • 2020-12-05 07:42

    You didn't cover the case convertView != null, this is what happens when scrolling up and down. You should implement a way to recycle the convertView (better) or just ignore it and give a fresh View back in this case too (worse).

    0 讨论(0)
  • 2020-12-05 07:43

    I solved my problem just changing the "setOnCheckedChangeListener" to "setOnClickListener"

    public View getView(final int position, View convertView, ViewGroup parent) {
    
        ViewHolder holder;
    
        if (convertView == null) {
    
            CheckBox cbItemChecklist = new CheckBox(context);
    
            holder = new ViewHolder();
            holder.cbItemChecklist = cbItemChecklist;
    
            convertView = cbItemChecklist;
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
    
        final ItemChecklist itemChecklist = itensChecklist.get(position);
    
        holder.cbItemChecklist.setText(itemChecklist
                .getDescricaoItemChecklist());
        holder.cbItemChecklist.setChecked(itemChecklist.isChecked());
        holder.cbItemChecklist
                .setOnClickListener(new OnClickListener() {
    
                    @Override
                    public void onClick(View v) {
                        if(itemChecklist.isChecked()){
                            itemChecklist.setChecked(false);
                        } else {
                            itemChecklist.setChecked(true);                         
                        }
    
    
                    }
                });
        return convertView;
    }
    
    0 讨论(0)
  • 2020-12-05 07:54

    I have a good alternative for a CheckBox. You can use android:state_activated="true" for your ListView rows. It does not lose its state and does not require lots of code.

    Here is how to works

    • create active_row.xml in your drawable folder


    <selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_activated="true"        
              android:drawable="@android:color/darker_gray"/>
     </selector>   
    
    • Set the the Background of your Row layout as android:background="@drawable/active_row.xml"
    • And finally add this to your ListView android:choiceMode="multipleChoice"

    You can check the State of every row like this

    View v;
    
    LinearLayout yourRowLayout;
    for (int i = 0; i < yourListView.getChildCount(); i++) {
    v = yourListView.getChildAt(i);
    yourRowLayout = (LinearLayout) v.findViewById(R.id. yourRowLayout);
    if(yourRowLayout.isActivated()){....  }  }
    
    0 讨论(0)
  • 2020-12-05 07:55

    Use setTag() in adapter. You can see example here Example listview with checkbox scroll issue

    0 讨论(0)
  • 2020-12-05 07:58

    check this code

    public class NewQAAdapterSelectFriends extends BaseAdapter {
    private LayoutInflater mInflater;
    private Person[] data;
    ArrayList<String> checkedItem=new ArrayList<String>();
    
    public NewQAAdapterSelectFriends(Context context) { 
        mInflater = LayoutInflater.from(context);
    }
    
    public void setData(Person[] data) {
        this.data = data;
    }
    
    @Override
    public int getCount() {
        return data.length;
    }
    
    @Override
    public Object getItem(int item) {
        return data[item];
    }
    
    @Override
    public long getItemId(int position) {
        return position;
    }
    
    
    
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item_select_friends, null);
            final ViewHolder viewHolder = new ViewHolder();
            viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName);
            viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname);
            viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage);
            viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox);
            convertView.setTag(viewHolder);
            viewHolder.nameText.setTag(viewHolder.nameText);
            viewHolder.nameText.setTag(viewHolder.surnameText);
            viewHolder.contactImage.setTag(data[position]);
            viewHolder.checkBox.setOnCheckedChangeListener(
                    new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
                            Person element = (Person) viewHolder.checkBox.getTag();
    
                            if(isChecked){
                                getCheckList(data[position],isChecked);
                            }
                            else{
                                getCheckList(data[position],isChecked);    
                            }
    
                        }
                    });
            viewHolder.checkBox.setTag(data[position]);
        } 
         ViewHolder holder = (ViewHolder) convertView.getTag();
         holder.nameText.setText(data[position].getName());
         holder.surnameText.setText(data[position].getSurname());
         holder.contactImage.setImageResource(data[position].getPhotoRes());
         holder.contactImage.setScaleType(ScaleType.FIT_XY);
         if(checkedItem != null && checkedItem.contains(data[position])){
            viewHolder.checkBox.setChecked(true);
         }else
         {
            viewHolder.checkBox.setChecked(false);
         } 
        return convertView;
    }
    
    static class ViewHolder {
        TextView nameText;
        TextView surnameText;
        ImageView contactImage;
        CheckBox checkBox;
    }
    public void getCheckList(String value,boolean status){
            if(!checkedItem.contains(value)  && status)
            {
                checkedItem.add(value);
            }
            if(checkedItem.contains(value)  && !status)
            {
                checkedItem.remove(value);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 07:59

    You are setting the tag of the checkbox only if convertview is null. This happens only for the first screen of records. When user scrolls down, the previous convertviews are recycled. Thus your checkboxes have older data items as their tags.

    Your checked change listener should look like this:

    new CompoundButton.OnCheckedChangeListener()
    {
        @Override
        public void onCheckedChanged(CompoundButton buttonView,boolean isChecked)
        {
            Person element = (Person) viewHolder.checkBox.getTag();
    
            data[position].setCheck(isChecked);
    
            if(isChecked)
            {
                // do your stuff
            }
            else
            {
                //to-do
            }
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题