我的ListView中的搜索过滤器存在一些问题。当我在搜索框中键入我的对象的字母时,它会正常搜索。但是当我添加其他内容时,尽管它不包含该文本,但这些项仍保留在ListView中。你可以在图片中看到它。
你有什么想法,如何解决这个问题?
带过滤器类的适配器(如下):
public class AnimalAdapter extends ArrayAdapter<Animal> implements Filterable{
private Context mContext;
private List<Animal> mAnimals;
ImageLoader imageLoader;
DisplayImageOptions options;
Activity activity;
AnimalAdapter adapter;
private Filter animalFilter;
private List<Animal> animaly;
ListView mListView;
RelativeLayout row;
@SuppressWarnings("deprecation")
public AnimalAdapter(Context context, List<Animal> objects) {
super(context, R.layout.animal_row_item, objects);
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context).build();
imageLoader = ImageLoader.getInstance();
imageLoader.init(config);
options = new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.build();
this.mContext = context;
this.mAnimals = objects;
this.animaly = objects;
}
public View getView(int position, View convertView, ViewGroup parent){
if(convertView == null){
LayoutInflater mLayoutInflater = LayoutInflater.from(mContext);
convertView = mLayoutInflater.inflate(R.layout.animal_row_item, null);
}
final Animal animal = mAnimals.get(position);
TextView animalView = (TextView) convertView.findViewById(R.id.animal_text);
TextView areaView = (TextView) convertView.findViewById(R.id.area_text);
final ImageView animalPic = (ImageView)convertView.findViewById(R.id.animal_pic);
final ProgressBar indicator = (ProgressBar)convertView.findViewById(R.id.progress);
indicator.setVisibility(View.VISIBLE);
animalPic.setVisibility(View.INVISIBLE);
//Setup a listener we can use to switch from the loading indicator to the Image once it's ready
ImageLoadingListener listener = new ImageLoadingListener(){
@Override
public void onLoadingStarted(String arg0, View arg1) {
// TODO Auto-generated method stub
}
@Override
public void onLoadingCancelled(String arg0, View arg1) {
// TODO Auto-generated method stub
}
@Override
public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {
indicator.setVisibility(View.INVISIBLE);
animalPic.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String arg0, View view, FailReason arg2) {
}
};
imageLoader.displayImage(animal.getImgUrl(), animalPic,options, listener);
animalView.setText(animal.getAnimal());
areaView.setText(animal.getArea());
convertView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getContext(), MoreActivity.class);
intent.putExtra("about", animal.getAbout());
intent.putExtra("animal", animal.getAnimal());
intent.putExtra("imgUrl", animal.getImgUrl());
getContext().startActivity(intent);
}
});
return convertView;
}
public int getCount() {
return mAnimals.size();
}
@Override
public Filter getFilter() {
if (animalFilter == null)
animalFilter = new AnimalFilter();
return animalFilter;
}
private class AnimalFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// We implement here the filter logic
if (constraint == null || constraint.length() == 0) {
// No filter implemented we return all the list
results.values = animaly;
results.count = animaly.size();
}
if (constraint!= null && constraint.toString().length() > 0) {
List<Animal> nAnimalList = new ArrayList<Animal>();
for (Animal p : animaly) {
if (p.getAnimal().toUpperCase().contains(constraint.toString().toUpperCase())
&&p.getAnimal().toUpperCase().startsWith(constraint.toString().toUpperCase()))
nAnimalList.add(p);
if (p.getAnimal().toUpperCase().contains(constraint.toString().toUpperCase())
&&!p.getAnimal().toUpperCase().startsWith(constraint.toString().toUpperCase()))
nAnimalList.remove(p);
}
results.values = nAnimalList;
results.count = nAnimalList.size();
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
// Now we have to inform the adapter about the new list filtered
if (results.count == 0)
notifyDataSetInvalidated();
else {
mAnimals = (List<Animal>) results.values;
notifyDataSetChanged();
}
}
}
}
答案 0 :(得分:1)
试试这个:
if (constraint!= null && constraint.toString().length() > 0) {
List<Animal> nAnimalList = new ArrayList<Animal>();
for (Animal p : animaly) {
if (p.getAnimal().toUpperCase().contains(constraint.toString().toUpperCase()))
nAnimalList.add(p);
}
results.values = nAnimalList;
results.count = nAnimalList.size();
}
答案 1 :(得分:1)
虽然我认为填充List的逻辑可能已关闭(即不需要在开始为空的列表上执行.remove()),但您的错误可能在publishResults中:
if (results.count == 0)
notifyDataSetInvalidated(); // <-- this isn't right
else
{
mAnimals = (List<Animal>) results.values;
notifyDataSetChanged();
}
notifyDataSetInvalidated()可能不是您要清空列表的目的,而是执行此操作:
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
// even if results.values is an empty List<Animal>, you want to notify your adapter!
mAnimals = (List<Animal>) results.values;
notifyDataSetChanged();
}
答案 2 :(得分:0)
if (p.getAnimal().toUpperCase().contains(constraint.toString().toUpperCase())
&& !p.getAnimal().toUpperCase().startsWith(constraint.toString().toUpperCase())) {
nAnimalList.remove(p);
}
让我们看一下每个语句的评估结果。第一个是假的,因为“熊猫”不包含“pansjdghas”。第二个是正确的,因为“熊猫”并不是以“pansdjlha”开头,而是你否定它以使其成为现实。因为第一个是假的,你永远不会到达删除动物的代码。要解决这个问题,只需否定第一个语句就可以了。您的代码现在应该如下所示:
if (!p.getAnimal().toUpperCase().contains(constraint.toString().toUpperCase())
&& !p.getAnimal().toUpperCase().startsWith(constraint.toString().toUpperCase())) {
nAnimalList.remove(p);
}