由于过滤通常需要比TextWatcher事件监听器更长的时间,因此您无法在TextWatcher中获得正确的过滤项计数。因此,在afterTextChanged()中,您会得到不正确的autoComplete.getAdapter().getCount()。我建议使用自定义侦听器,每当过滤项更改时就会调用它。
我将提供2种类似的方法:使用单独的类和仅使用1个类。
方法1:
您的适配器应如下所示:
import android.content.Context;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import java.util.ArrayList;
import java.util.List;
public class AutoCompleteAdapter extends ArrayAdapter
{
private List<String> tempItems;
private List<String> suggestions;
private FilterListeners filterListeners;
public AutoCompleteAdapter(Context context, int resource, List<String> items)
{
super(context, resource, 0, items);
tempItems = new ArrayList<>(items);
suggestions = new ArrayList<>();
}
public void setFilterListeners(FilterListeners filterFinishedListener)
{
filterListeners = filterFinishedListener;
}
@Override
public Filter getFilter()
{
return nameFilter;
}
Filter nameFilter = new Filter()
{
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
if (constraint != null)
{
suggestions.clear();
for (String names : tempItems)
{
if (names.toLowerCase().startsWith(constraint.toString().toLowerCase()))
{
suggestions.add(names);
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
}
else
{
return new FilterResults();
}
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
List<String> filterList = (ArrayList<String>) results.values;
if (filterListeners != null && filterList!= null)
filterListeners.filteringFinished(filterList.size());
if (results != null && results.count > 0)
{
clear();
for (String item : filterList)
{
add(item);
notifyDataSetChanged();
}
}
}
};
}
一个用于通知您筛选完成的接口:
public interface FilterListeners
{
void filteringFinished(int filteredItemsCount);
}
而且您可以使用它:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.AutoCompleteTextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements FilterListeners
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AutoCompleteTextView autoComplete = (AutoCompleteTextView) findViewById(R.id.autoComplete);
autoComplete.setThreshold(1);
List<String> stringList = new ArrayList<>();
stringList.add("Black");
stringList.add("White");
stringList.add("Yellow");
stringList.add("Blue");
stringList.add("Brown");
final AutoCompleteAdapter adapter = new AutoCompleteAdapter(this, android.R.layout.simple_list_item_1, stringList);
adapter.setFilterListeners(this);
autoComplete.setAdapter(adapter);
}
@Override
public void filteringFinished(int filteredItemsCount)
{
Log.i("LOG_TAG", " filteringFinished count = " + filteredItemsCount);
}
}
方法2:
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Filter;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final AutoCompleteTextView autoComplete = (AutoCompleteTextView) findViewById(R.id.autoComplete);
autoComplete.setThreshold(1);
final List<String> stringList = new ArrayList<>();
stringList.add("Black");
stringList.add("White");
stringList.add("Yellow");
stringList.add("Blue");
stringList.add("Brown");
final ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, stringList)
{
private List<String> tempItems = stringList;
private List<String> suggestions = new ArrayList<>();
@Override
public Filter getFilter()
{
return nameFilter;
}
Filter nameFilter = new Filter()
{
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
if (constraint != null)
{
suggestions.clear();
for (String names : tempItems)
{
if (names.toLowerCase().startsWith(constraint.toString().toLowerCase()))
{
suggestions.add(names);
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
}
else
{
return new FilterResults();
}
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
List<String> filterList = (ArrayList<String>) results.values;
filteringFinished(filterList.size());
if (results != null && results.count > 0)
{
clear();
for (String item : filterList)
{
add(item);
notifyDataSetChanged();
}
}
}
};
};
autoComplete.setAdapter(arrayAdapter);
}
private void filteringFinished(int filteredItemsCount)
{
Log.i("LOG_TAG", " filteringFinished count = " + filteredItemsCount);
}
}
当您输入内容并进行过滤时,
filteringFinished()
方法将被调用,与自动完成输入字段相关。
更新 ( Trie 搜索):
我创建了一个 Github 项目,其中包含使用
Trie搜索算法来大大提高自动完成性能的简单示例。
https://github.com/saqada/android-AutoCompleteWithTrie