检查:
我正在尝试在ListView
上实施过滤器。但我面临一个非常奇怪的问题。如果我在T
中输入字母EditText
,则ListView
的名称将从B
,J
开始填充。请帮忙。
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();
Log.e("Name", name);
final String numbr = map.get("Phone").toString();
Log.e("Number", numbr);
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 :(得分:3)
您的问题来自于您设置getView()
方法的方式以及如何在SparseBooleanArray中设置选中的项目。我已经编辑了适配器的代码,它现在应该可以工作了。主要更改位于OnCheckedChangeListener
字段:
public class MyCustomAdapter extends BaseAdapter implements Filterable {
private Context mContext;
private LayoutInflater mInflater;
private SparseBooleanArray mSparseBooleanArray;
// from where do you get the data?
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");
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);
mAdapData.add(NameNumber);
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.adapters_specialfilterrow,
paramViewGroup, false);
viewHolder.tvName = (TextView) paramView
.findViewById(R.id.textView1);
viewHolder.tvNumber = (TextView) paramView
.findViewById(R.id.textView2);
viewHolder.cb = (CheckBox) paramView.findViewById(R.id.checkBox1);
paramView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) paramView.getTag();
}
viewHolder.cb.setTag(paramInt);
viewHolder.cb.setOnCheckedChangeListener(null);
viewHolder.cb.setChecked(mSparseBooleanArray.get(paramInt));
viewHolder.cb.setOnCheckedChangeListener(mCheckedChangeListener);
viewHolder.tvName.setTextColor(Color.BLACK);
viewHolder.tvNumber.setTextColor(Color.BLACK);
Map<String, String> map = (Map<String, String>) mAdapData.get(paramInt);
final String name = map.get("Name");
final String numbr = map.get("Phone");
viewHolder.tvName.setText(name);
viewHolder.tvNumber.setText(numbr);
return paramView;
}
OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// get the item from the current mAdapData
Map<String, String> item = mAdapData.get((Integer) buttonView
.getTag());
int position = -1;
// see where is the item placed in the mOriginalData and use that
// position
for (int i = 0; i < mOriginalData.size(); i++) {
final Map<String, String> tmp = mOriginalData.get(i);
if (tmp.get("Name").toLowerCase().equals(item.get("Name").toLowerCase())) {
position = i;
break;
}
}
mSparseBooleanArray.put(position, 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");
final String numbr = map.get("Phone");
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();
}
}
}
答案 1 :(得分:1)
在getView()
方法中,您没有更新UI以获得过滤结果的值。
所以它返回了旧结果的视图。
在返回paramView之前,将视图的数据更新为过滤结果中的数据,并将其从viewHolder的准备中删除,因为这只被调用了几次。
编辑: 这是我对代码的更正。我认为它会解决它:
@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.tvName.setTextColor(Color.BLACK);
viewHolder.tvNumber.setTextColor(Color.BLACK);
paramView.setTag(viewHolder);
viewHolder.cb.setOnCheckedChangeListener(mCheckedChangeListener);
} else {
viewHolder = (ViewHolder) paramView.getTag();
}
viewHolder.cb.setTag(paramInt);
viewHolder.cb.setChecked(mSparseBooleanArray.get(paramInt));
Map<String, String> map = (Map<String, String>) mAdapData.get(paramInt);
final String name = map.get("Name").toString();
Log.e("Name", name);
final String numbr = map.get("Phone").toString();
Log.e("Number", numbr);
viewHolder.tvName.setText(name);
viewHolder.tvNumber.setText(numbr);
return paramView;
}
编辑: 这是我如何处理过滤的示例:
@Override
public Filter getFilter()
{
final Filter filter=new Filter()
{
@Override
protected FilterResults performFiltering(final CharSequence constraint)
{
_lastFilterConstraint=constraint;
if(TextUtils.isEmpty(constraint))
return null;
final String constraintToCheck=constraint.toString().toLowerCase(Locale.getDefault());
final FilterResults results=new FilterResults();
// <- here i do the filtering itself and later put the results into "results"
results.values=values;
results.count=values.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(final CharSequence constraint,final FilterResults results)
{
_filteredItems==null ? null : (ArrayList<Item>)results.values;
notifyDataSetChanged();
}
};
return filter;
}
@Override
public int getCount()
{
if(_filteredItems!=null)
return _filteredItems.size();
return _originalItems.size();
}
@Override
public Item getItem(final int position)
{
if(_filteredItems!=null)
{
if(position<_filteredItems.size())
return _filteredItems.get(position);
return null;
}
if(position<_originalItems.size())
return _originalItems.get(position);
return null;
}
@Override
public View getView(final int position,final View convertView,final ViewGroup parent)
{
final View inflatedView;
final ViewHolder viewHolder;
if(convertView==null)
{
//<- here i inflate the view into the inflatedView
}
else
{
inflaterView=convertView;
viewHolder=(ViewHolder)inflaterView.getTag();
}
// <- here i use getItem and update the view according to its data .
return inflaterView;
}
答案 2 :(得分:1)
我还在我的应用程序中实现了过滤器列表视图。为此,我只需要一段代码。检查它,如果它有帮助。
editText.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
}
public void afterTextChanged(Editable arg0) {
sendToList.this.adapter.getFilter().filter(arg0);
}
});