AutoCompleteTextView 的自定义过滤器在单击时返回错误的字符串
Posted
技术标签:
【中文标题】AutoCompleteTextView 的自定义过滤器在单击时返回错误的字符串【英文标题】:Custom Filter for AutoCompleteTextView returns wrong string on click 【发布时间】:2018-09-09 11:45:32 【问题描述】:我为我的AutoCompleteTextView
编写了自定义ArrayAdapter
和自定义Filter
。它正确显示了所有内容,但是当我过滤建议并单击一个项目时,它会获取显示所有项目时建议列表中此位置的项目的字符串。我做了截图来澄清我的意思:
这是我的代码:
public class AutoCompleteCountryAdapter extends ArrayAdapter<CountryItem>
private List<CountryItem> countryList;
private List<CountryItem> filteredCountryList = new ArrayList<>();
public AutoCompleteCountryAdapter(@NonNull Context context, @NonNull List<CountryItem> countryList)
super(context, 0, countryList);
this.countryList = countryList;
@Override
public int getCount()
return filteredCountryList.size();
@NonNull
@Override
public Filter getFilter()
return countryFilter;
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent)
CountryItem countryItem = filteredCountryList.get(position);
LayoutInflater inflater = LayoutInflater.from(getContext());
if (convertView == null)
convertView = inflater.inflate(
R.layout.country_autocomplete_row, parent, false
);
TextView textViewName = convertView.findViewById(R.id.text_view_name);
ImageView imageViewFlag = convertView.findViewById(R.id.image_view_flag);
textViewName.setText(countryItem.getCountryName());
imageViewFlag.setImageResource(countryItem.getFlagImage());
return convertView;
private Filter countryFilter = new Filter()
private List<CountryItem> suggestions = new ArrayList<>();
@Override
protected FilterResults performFiltering(CharSequence constraint)
suggestions.clear();
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0)
suggestions.addAll(countryList);
else
String filterPattern = constraint.toString().toLowerCase().trim();
for (CountryItem item : countryList)
if (item.getCountryName().toLowerCase().contains(filterPattern))
suggestions.add(item);
results.values = suggestions;
results.count = suggestions.size();
return results;
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
filteredCountryList.clear();
filteredCountryList.addAll((List) results.values);
notifyDataSetChanged();
@Override
public CharSequence convertResultToString(Object resultValue)
return ((CountryItem) resultValue).getCountryName();
;
【问题讨论】:
你能把处理列表点击的活动代码贴出来 我不处理那里的点击,它在过滤器的 convertResultToString 方法中处理。但对我来说,它显示的结果与下拉列表中的结果不同 【参考方案1】:我解决了。 我不知道为什么这没有出现在我找到的任何教程中(包括 Materialdoc 教程),但您还必须在适配器中覆盖 getItem,以便从过滤后的列表中选择它的项目,而不是从原始列表中选择:
public CountryItem getItem(int position)
return filteredCountryList.get(position);
【讨论】:
【参考方案2】:我为过滤用户联系人的用户联系人适配器提供了一个使用 recylerview 适配器的适配器类。您可以根据代码更改您的要求..
public class InviteContactAdapter extends RecyclerView.Adapter<InviteContactAdapter.ItemViewHolder> implements Filterable
private List<UserContact> mContactList = new ArrayList<>();
private List<UserContact> mContectFilter = new ArrayList<>();
private Context mContext;
private CustomFilter mFilter;
public List<String> mEmailList = new ArrayList<>();
public InviteContactAdapter(Context context, List<UserContact> mContactList)
mContext = context;
this.mContactList = mContactList;
this.mContectFilter = mContactList;
mFilter = new CustomFilter();
public onItemClickListener onItemClickListener;
public void setOnItemClickListener(InviteContactAdapter.onItemClickListener onItemClickListener)
this.onItemClickListener = onItemClickListener;
@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.invite_contact_row_layout, viewGroup, false);
return new ItemViewHolder(view);
public interface onItemClickListener
void onClick(UserContact contact);
@Override
public Filter getFilter()
return mFilter;
@Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int i)
final UserContact contact = mContectFilter.get(i);
itemViewHolder.mTvUserNane.setText(contact.getUserName().trim());
itemViewHolder.mTvUserEmail.setText(contact.getUserEmail().trim());
if (contact.isSelect())
itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
else
itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);
itemViewHolder.itemView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
if (contact.isSelect())
contact.setSelect(false);
itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);
else
contact.setSelect(true);
itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
);
@Override
public int getItemCount()
return mContectFilter.size();
public class ItemViewHolder extends RecyclerView.ViewHolder
private TextView mTvUserNane, mTvUserEmail;
private ImageView mIvSelect;
public ItemViewHolder(View itemView)
super(itemView);
mTvUserEmail = itemView.findViewById(R.id.icrlTvUserEmail);
mTvUserNane = itemView.findViewById(R.id.icrlTvUserName);
mIvSelect = itemView.findViewById(R.id.icrlIvSelect);
public List<String> getEmail()
mEmailList.clear();
for (UserContact contact : mContectFilter)
if (contact.isSelect())
mEmailList.add(contact.getUserEmail());
return mEmailList;
/**
* this class for filter data.
*/
class CustomFilter extends Filter
@Override
protected FilterResults performFiltering(CharSequence charSequence)
FilterResults results = new FilterResults();
if (charSequence != null && charSequence.length() > 0)
ArrayList<UserContact> filters = new ArrayList<>();
charSequence = charSequence.toString().toUpperCase();
for (int i = 0; i < mContactList.size(); i++)
if (mContactList.get(i).getUserName().toUpperCase().contains(charSequence) || mContactList.get(i).getUserEmail().toUpperCase().contains(charSequence))
UserContact contact = new UserContact();
contact.setUserName(mContactList.get(i).getUserName());
contact.setUserEmail(mContactList.get(i).getUserEmail());
filters.add(contact);
results.count = filters.size();
results.values = filters;
else
results.count = mContactList.size();
results.values = mContactList;
return results;
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults)
mContectFilter = (ArrayList<UserContact>) filterResults.values;
notifyDataSetChanged();
【讨论】:
【参考方案3】:ArrayList<YourModel> arrayList = new ArrayList<>();
arrayList.addAll(yourList);
AutoCompleteAdapter autoCompleteAdapter = new AutoCompleteAdapter(context, arrayList);
autoCompleteTextView.setAdapter(brandAdapter);
autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
YourModel model = (YourModel) autoCompleteAdapter.getItem(position);
autoCompleteTextView.setText(model.getText());
autoCompleteTextView.setSelection(model.getText().length());
);
AutoCompleteAdapter.java
public class AutoCompleteAdapter extends BaseAdapter implements Filterable
private Context context;
private ArrayList<YourModel> originalList;
private ArrayList<YourModel> suggestions = new ArrayList<>();
private Filter filter = new CustomFilter();
public AutoCompleteAdapter(Context context, ArrayList<YourModel> originalList)
this.context = context;
this.originalList = originalList;
@Override
public View getView(int position, View convertView, ViewGroup parent)
try
if (convertView == null)
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_filter, parent, false);
YourModel model = suggestions.get(position);
AppCompatTextView tvTitle = convertView.findViewById(R.id.tvTitle);
tvTitle.setText(model.getText());
catch (NullPointerException e)
e.printStackTrace();
catch (Exception e)
e.printStackTrace();
return convertView;
@Override
public Object getItem(int position)
return suggestions.get(position);
@Override
public long getItemId(int position)
return 0;
@Override
public int getCount()
return suggestions.size();
@Override
public Filter getFilter()
return filter;
private class CustomFilter extends Filter
@Override
protected FilterResults performFiltering(CharSequence constraint)
suggestions.clear();
if (originalList != null && constraint != null)
for (int i = 0; i < originalList.size(); i++)
if (originalList.get(i).getText().toLowerCase().contains(constraint.toString().toLowerCase().trim()))
suggestions.add(originalList.get(i));
FilterResults results = new FilterResults();
results.values = suggestions;
results.count = suggestions.size();
return results;
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
if (results.count > 0)
notifyDataSetChanged();
else
notifyDataSetInvalidated();
【讨论】:
以上是关于AutoCompleteTextView 的自定义过滤器在单击时返回错误的字符串的主要内容,如果未能解决你的问题,请参考以下文章
在AutocompleteTextview的下拉列表中自定义分隔符/分隔符
将其值设置为“”后无法过滤 AutoCompleteTextView
Android自己主动提示文本框(AutoCompleteTextView)
AutoCompleteTextView(自动完成文本框)的基本使用