自定义 AutoCompleteTextView 行为
Posted
技术标签:
【中文标题】自定义 AutoCompleteTextView 行为【英文标题】:Custom AutoCompleteTextView behavior 【发布时间】:2012-02-20 09:46:54 【问题描述】:开箱即用,AutoCompleteTextView
小部件似乎无法匹配列表值中间的输入字符串 - 匹配总是在开头进行;例如,输入“ar
”匹配“argentina
”,但不匹配“hungary
”。
如何搜索单词中间的文字?谁能给我一个想法?
提前致谢!
【问题讨论】:
我在这里做类似的事情!!! ***.com/questions/12854336/… 【参考方案1】:您需要编写一个自定义的Filter
类并自己实现performFiltering
方法。此方法采用CharSequence
参数,您可以使用该参数执行所需的任何字符串操作,以便从数据集中生成匹配列表(在您的情况下,您可以使用String.contains
而不是String.startsWith
)。 performFiltering
函数不在 UI 线程上运行。
然后您将匹配列表作为FilterResults
对象返回,其中包含Object
值(您的匹配列表,可能是ArrayList
)和int
count 这是匹配列表的大小。
最后,实现 publishResults
回调方法,一旦工作线程生成匹配列表,该方法就会返回,允许您在 AutoCompleteTextView 的适配器上调用 notifyDataSetChanged
以便它可以显示结果。
【讨论】:
你能举个例子吗? 我知道距离这个答案已经有很长时间了,但它是我发现的关于这个主题的最准确的答案之一(顺便说一句,也是最难找到的答案之一)。谢谢! Victor 是对的,这是一种简单的方法:只需将 android.widget.ArrayAdapter 的全部内容复制粘贴到一个名为 CustomArrayAdapter 的新类中,然后更改位于 performFiltering 和 publishResults 中的 2 个“startsWith”事件通过“包含”。很简单。【参考方案2】:老问题,但仍然相关。在其他几个问题的指导下,使用 filterable 实现了一个自定义适配器。我制作了一个简单的通用适配器,可以使用包含进行搜索。关于它的快速注释:
我使用的是butterknife,但是用findviewbyid 很容易做viewHolder。
布局 R.layout.list_item_simple 是带有文本视图 R.id.text_view_simple 的简单布局。
对象需要一个 toString 来进行比较。
public class SimpleContainsAutocompleteAdapter <T> extends ArrayAdapter<T> implements Filterable
private List <T> listObjects;
List<T> suggestions = new ArrayList<>();
private int resource;
private Filter mFilter = new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
FilterResults filterResults = new FilterResults();
if(constraint != null)
suggestions.clear();
for(T object : listObjects)
if(object.toString().toLowerCase().contains(constraint.toString().toLowerCase()))
suggestions.add(object);
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
@Override
protected void publishResults(CharSequence contraint, FilterResults results)
if(results == null)
return;
List<T> filteredList = (List<T>) results.values;
if(results.count > 0)
clear();
for (T filteredObject : filteredList)
add(filteredObject);
notifyDataSetChanged();
;
public SimpleContainsAutocompleteAdapter(Context context, List<T> listObjects)
super(context, R.layout.list_item_simple, listObjects);
this.listObjects = new ArrayList<>(listObjects);
this.resource = R.layout.list_item_simple;
@Override
public Filter getFilter()
return mFilter;
@Override
public View getView(int position, View convertView, ViewGroup parent)
Object listObject = getItem(position);
viewHolder holder;
if(convertView != null)
holder = (viewHolder) convertView.getTag();
else
convertView = LayoutInflater.from(getContext()).inflate(resource, parent, false);
holder = new viewHolder(convertView);
convertView.setTag(holder);
holder.name.setText(listObject.toString());
return convertView;
static class viewHolder
@InjectView(R.id.text_view_simple) TextView name;
public viewHolder(View view)
ButterKnife.inject(this, view);
【讨论】:
这就是答案,我不得不改变一些东西,但效果很好。【参考方案3】:public class AutoCompleteAdapter <T> extends ArrayAdapter<T> implements Filterable
private List <T> listObjects;
List<T> suggestions = new ArrayList<>();
private Context context;
public AutoCompleteAdapter(Context context, List<T> listObjects)
super(context, R.layout.list_item_simple, listObjects);
this.listObjects = new ArrayList<>(listObjects);
this.context = context;
private Filter mFilter = new Filter()
@Override
protected FilterResults performFiltering(CharSequence constraint)
FilterResults filterResults = new FilterResults();
if(constraint != null)
suggestions.clear();
for(T object : listObjects)
if(object.toString().toLowerCase().contains(constraint.toString().toLowerCase())) suggestions.add(object);
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
if(results == null)
return;
List<T> filteredList = (List<T>) results.values;
if(results.count > 0)
clear();
for (T filteredObject : filteredList)
add(filteredObject);
notifyDataSetChanged();
;
@Override
public Filter getFilter()
return mFilter;
private static class ViewHolder
TextView title;
@Override
public View getView(int position, View convertView, ViewGroup parent)
Object listObject = getItem(position);
final ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null)
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.list_item_simple, parent, false);
viewHolder.title = (TextView) convertView.findViewById(R.id.title);
convertView.setTag(viewHolder);
else
viewHolder = (ViewHolder) convertView.getTag();
viewHolder.title.setText(listObject.toString());
return convertView;
【讨论】:
【参考方案4】:我的建议是将字符串解析为字符数组。 然后迭代每个字符,直到找到字符串。
例如,假设您的搜索想要返回所有带有“ate”的单词,而单词列表是...
状态 特征 斥责 迟到
你的算法应该是这样的
获取字符串并将其解析为字符数组 遍历数组并找到第一个“正确字符”(在我们的示例中为“a”) 找到该字符后,检查下一个字符,继续检查每个字符是否匹配,直到要搜索的值完成。如果字符不匹配,则退出数组迭代并转到下一个单词。
【讨论】:
以上是关于自定义 AutoCompleteTextView 行为的主要内容,如果未能解决你的问题,请参考以下文章
AutoCompleteTextView 的自定义过滤器在单击时返回错误的字符串
将其值设置为“”后无法过滤 AutoCompleteTextView
Arraylist 中有 1000 个条目的 AutocompleteTextView 不起作用
Android自己主动提示文本框(AutoCompleteTextView)