打勾(选中)复选框的postition列表视图的滤波后的数据改变(postition of tick

2019-08-04 12:40发布

我想在延伸我的自定义适配器应用滤镜BaseAdapter基于文本,在我面临的一些问题,经过我过滤输入EditText和检查CheckBox以选择一个值,如果我删除的文字EditText来寻找一些其他的东西,你可以在下面安装在图像看到选中的复选框的位置自动改变。 我目前面临两个问题

1 - 选中的复选框的位置自动改变

2 -如果我在大写输入EditTextListView一片空白。

public class MyCustomAdapter extends BaseAdapter implements Filterable {

Context mContext;
private LayoutInflater mInflater;
SparseBooleanArray mSparseBooleanArray;
private ArrayList<Map<String,String>> mAdapData = new ArrayList<Map<String, String>>();
private ArrayList<Map<String,String>> mOriginalData = new ArrayList<Map<String, String>>();

public MyCustomAdapter(Context mContext) {
    mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mSparseBooleanArray = new SparseBooleanArray();
}

public ArrayList<String> getCheckedItems() {
    ArrayList<String> mTempArry = new ArrayList<String>();
    for (int i = 0; i < mAdapData.size(); i++) {
        if (mSparseBooleanArray.get(i)) {
            Map<String, String> map = (Map<String, String>) mAdapData.get(i);
            final String numbr = map.get("Phone").toString();
            mTempArry.add(numbr);
        }
    }
    return mTempArry;
}

@Override
public int getCount() {
    return this.mAdapData.size();
}

public void addItem(String paramString1, String paramString2) {
    Map<String, String> NameNumber = new HashMap<String, String>();
    NameNumber.put("Name", paramString1);
    NameNumber.put("Phone", paramString2);
    this.mAdapData.add(NameNumber);
    this.mOriginalData.add(NameNumber);
    notifyDataSetChanged();
}

@SuppressWarnings("unchecked")
public Object getItem(int paramInt) {
    return (ArrayList<Map<String, String>>) this.mAdapData.get(paramInt);
}

@Override
public long getItemId(int paramInt) {
    return paramInt;
}

@Override
public View getView(final int paramInt, View paramView, ViewGroup paramViewGroup) {

    ViewHolder viewHolder;

    if (paramView == null) {
        viewHolder = new ViewHolder();
        paramView = mInflater.inflate(R.layout.multiplecontactview, null);
        viewHolder.tvName = (TextView) paramView.findViewById(R.id.txtContactName);
        viewHolder.tvNumber = (TextView) paramView.findViewById(R.id.txtContactNumber);
        viewHolder.cb = (CheckBox) paramView.findViewById(R.id.checkBox1);
        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);
        }
        paramView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) paramView.getTag();
    }       
    return paramView;
}

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

public static class ViewHolder {
    TextView tvName;
    TextView tvNumber;
    CheckBox cb;
}

@Override
public Filter getFilter() {
    return new MyContactFilter();
}

@SuppressLint("DefaultLocale")
private class MyContactFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();
        ArrayList<Map<String, String>> mFilteredData = new ArrayList<Map<String, String>>();

        if (!TextUtils.isEmpty(constraint)) { 
            for(int i = 0; i < mAdapData.size(); i++) {
                Map<String, String> map = (Map<String, String>) mAdapData.get(i);
                final String names = map.get("Name").toString();
                final String numbr = map.get("Phone").toString();
                if(names.toLowerCase().contains(constraint.toString().toLowerCase())) {
                    Map<String, String> FilNameNumber = new HashMap<String, String>();
                    FilNameNumber.put("Name", names);
                    FilNameNumber.put("Phone", numbr);
                    mFilteredData.add(FilNameNumber);
                }
            }
            results.values = mFilteredData;
            results.count = mFilteredData.size();

        } else {
            synchronized (mOriginalData) {
                results.values = mOriginalData;
                results.count = mOriginalData.size();
            }
        }
        return results;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence cs, FilterResults fr) {
        mAdapData = (ArrayList<Map<String, String>>) fr.values;
        notifyDataSetChanged();
    }
}
}

Answer 1:

如果你在你的代码看起来更认真,具体的getView()您将看到您创建ViewHolder独立的对象的时候convertView存在。

这是错误的使用ViewHolder模式。 相反,每次创建它的,创建它,只有当convertView为空,并将其设置为标签convertView通过setTag()否则得到参考ViewHolder使用getTag() 像这样:

 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;

另外,在您的preformFiltering()试图改变这个片段:

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

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

更新

有一些代码奇怪片段:

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

这意味着,如果你第一次检查列表项是在列表0位置,比SparseArray指示的第一项ListView应该始终有一个选中的框,因为你没有在你的代码的任何地方取消选中它,不要将该值设置为false,但做到这一点,只有当用户手动取消选中该复选框。



Answer 2:

摆脱复杂的映射的跟踪特性,将数据存储在像这样的一类,与选中状态一起:

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;
 }
}

内部getView()根据数据的状态设定对应的复选框,添加侦听器,以修改数据状态:

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);
    }
});

关于过滤:

names.toLowerCase().contains(cs)

Contains不区分大小写的匹配,对char值 。 尝试names.toLowerCase().contains(cs.toLowerCase())



文章来源: postition of ticked (checked) checkbox changes after filtering data of Listview