我尝试根据BaseAdapter
中的文字过滤输入并检查EditText
,在我的自定义适配器上应用过滤器,扩展CheckBox
我面临一些问题}选择一个值,如果我删除EditText
中的文本以搜索其他内容,则选中复选框的位置会自动更改,如下图所示。我目前面临两个问题
1 - 勾选复选框的位置会自动更改
2 - 如果我在EditText
中输入大写,则ListView
会变为空白。
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();
}
}
}
答案 0 :(得分: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())
答案 1 :(得分:1)
如果您更专注地查看代码,具体在getView()
上,您会看到每次创建ViewHolder
对象,而convertView
存在。
使用ViewHolder
模式是错误的。不是每次都创建它,而是仅在convertView
为空时创建它,并按convertView
将其设置为setTag()
的标记,否则使用{{1}获取对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()))
这意味着如果您第一次检查列表中0位置的列表项,则OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSparseBooleanArray.put((Integer) buttonView.getTag(), isChecked);
}
};
表示SparseArray
的第一项应始终具有复选框,因为如果您没有在代码中的任何位置取消选中它,请不要将该值设置为false,但仅在用户手动取消选中该复选框时才执行此操作。