AutoCompleteTextView自定义Filter点击返回错误字符串问题
解决AutoCompleteTextView自定义Adapter筛选后点击位置不匹配的问题
你遇到的这个问题是自定义ArrayAdapter结合Filter时的典型坑——筛选后的列表看起来正常,但点击时拿到的却是原始列表对应位置的数据,根本原因是你的Adapter没有正确维护筛选后的数据集,或者getItem()方法指向了错误的列表。
问题核心原因
当你完成筛选后,如果只是在performFiltering()里生成了筛选结果,但没在publishResults()中把Adapter的数据源替换成这个筛选后的列表,那getItem(position)还是会从原始的countryList里取数据。这就导致你点击筛选后的第N项,实际拿到的是原始列表第N项的内容,和你看到的筛选结果完全不匹配。
具体修复步骤
首先调整你的Adapter数据结构,要分开维护原始完整数据和筛选后结果数据:
public class AutoCompleteCountryAdapter extends ArrayAdapter<CountryItem> { private List<CountryItem> originalCountryList; // 保存原始全量数据 private List<CountryItem> filteredCountryList; // 保存筛选后的结果数据 // ...其他成员变量
然后按以下步骤修改关键方法:
初始化时保存原始数据
在构造方法里把传入的列表复制一份到原始列表,同时让筛选列表初始化为原始数据:public AutoCompleteCountryAdapter(Context context, int resource, List<CountryItem> countryItems) { super(context, resource, countryItems); this.originalCountryList = new ArrayList<>(countryItems); this.filteredCountryList = new ArrayList<>(countryItems); }重写
getItem()和getCount()方法
让这两个方法都指向筛选后的列表,而不是原始列表:@Override public CountryItem getItem(int position) { return filteredCountryList.get(position); } @Override public int getCount() { return filteredCountryList.size(); }正确实现Filter的
publishResults()方法
在这个方法里把筛选结果更新到筛选列表,并通知Adapter刷新:@Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); List<CountryItem> tempFilteredList = new ArrayList<>(); // 这里写你的筛选逻辑,基于originalCountryList生成筛选结果 if (constraint == null || constraint.length() == 0) { tempFilteredList.addAll(originalCountryList); } else { String filterText = constraint.toString().toLowerCase().trim(); for (CountryItem item : originalCountryList) { // 示例:根据国家名称筛选,你可以替换成自己的匹配逻辑 if (item.getCountryName().toLowerCase().contains(filterText)) { tempFilteredList.add(item); } } } results.values = tempFilteredList; results.count = tempFilteredList.size(); return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { filteredCountryList.clear(); filteredCountryList.addAll((List<CountryItem>) results.values); notifyDataSetChanged(); // 通知Adapter更新UI }
额外提醒
- 永远不要修改
originalCountryList,它要一直保存完整的原始数据,所有筛选操作都基于它来生成新的筛选列表。 - 如果你的
CountryItem是自定义对象,确保它的toString()方法返回你想在AutoCompleteTextView中显示的内容(或者你已经重写了getView()来自定义显示布局)。
这样修改后,点击筛选后的列表项时,就能拿到对应位置的正确数据了,不会再出现和原始列表位置匹配的错误。
内容的提问来源于stack exchange,提问作者Florian Walther
相关产品推荐
相关产品推荐

