postition of ticked (checked) checkbox changes after filtering data of Listview

对着背影说爱祢 提交于 2019-12-04 16:28:23

If you look at your code more attentively, concretely on the getView(), you'll see that you create ViewHolder object every time independently of convertView presence.

This is wrong using of ViewHolder pattern. Instead of creating it everytime, create it only when convertView is null and set it as the tag of convertView by setTag(), otherwise get the reference to ViewHolder using getTag(). Just Like this:

 ViewHolder viewHolder;

    if (paramView == null) {
        paramView = mInflater.inflate(R.layout.multiplecontactview, null);
        viewHolder = new ViewHolder();
        viewHolder.tvName = (TextView) paramView.findViewById(R.id.txtContactName);
        viewHolder.tvNumber = (TextView) paramView.findViewById(R.id.txtContactNumber);
        viewHolder.cb = (CheckBox) paramView.findViewById(R.id.checkBox1);
        paramView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) paramView.getTag();
    }

    viewHolder.cb.setTag(paramInt);
    viewHolder.cb.setChecked(mSparseBooleanArray.get(paramInt));
    viewHolder.cb.setOnCheckedChangeListener(mCheckedChangeListener);
    viewHolder.tvName.setTextColor(Color.BLACK);
    viewHolder.tvNumber.setTextColor(Color.BLACK);
    for (int i = 0; i < mAdapData.size(); i++) {
        Map<String, String> map = (Map<String, String>) mAdapData.get(paramInt);
        final String name = map.get("Name").toString();
        final String numbr = map.get("Phone").toString();
        viewHolder.tvName.setText(name);
        viewHolder.tvNumber.setText(numbr);
    }
    return paramView;

Also in your preformFiltering() try to change this snippet:

if (names.toLowerCase().contains(cs))

to

if (names.toLowerCase().contains(cs.toString().toLowerCase()))

Update

There is some strange snippet of code:

OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() {
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        mSparseBooleanArray.put((Integer) buttonView.getTag(), isChecked);
    }
};

It means that if you first time check the list item which is on the 0 position in the list, than SparseArray indicates that the first item of the ListView should always have a checked box, because you don't uncheck it anywhere in you code, don't set the value to false but do it only when user manually uncheck the checkbox.

Get rid of complex mappings to track properties, store the data in a class like this, along with checked state:

public class Data {
 private final String text;
 private boolean checked;

 public Data(String text){
   this.text = text;
   this.checked = false;
 }

 public void setChecked(boolean b){
   this.checked = b;
 }

 public boolean isChecked(){
   return this.checked;
 }

 public String getText(){
   return this.text;
 }
}

Inside getView() , set the checkbox according to data state, add listener to modify data state:

final Data data = getItem(position);

cb.setOnCheckedChangeListener(null); //important 
cb.setChecked(data.isChecked());
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        data.setChecked(isChecked);
    }
});

About filtering:

names.toLowerCase().contains(cs)

Contains does a case sensitive match, on char values. try names.toLowerCase().contains(cs.toLowerCase())

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!