2014-01-07 38 views
0

我的ListView中的搜索篩選器存在一些問題。當我將我的對象的字母輸入到搜索框中時,它會正常搜索。但是,當我添加其他任何東西時,儘管它不包含該文本,但這些項仍保留在ListView中。你可以在照片中看到它。ListView搜索篩選器會留下不受歡迎的數據

你有什麼想法,該如何解決?

Picture

適配器,帶過濾器類(如下圖):

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

偏題,但我喜歡可愛的小貓照片:3 – FWeigl

+0

lol haha​​ha。不錯的選擇吧? – marson

回答

1

雖然我覺得你的邏輯填充列表可能會關閉(即有沒有必要做一個.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(); 
} 
+0

謝謝你的回答CSmith。我該如何實現,當沒有結果適合時,列表將是空的。 (不以某個字母開始或不包含某些序列) – marson

+0

上述建議應該可行,假設您的列表由mAnimals填充,如果mAnimals引用空列表。 – CSmith

+0

經過幾分鐘的思考你的答案,我終於明白了。確實如此,但我認爲,如果我設置了函數contains和staetsWith,文本(例如「pandasnifsdni ...」)也會出現在那裏,因爲它至少包含部分序列。我真的嗎? – marson

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); 
} 
+0

我不太明白爲什麼動物必須被刪除。它不應該添加在第一個地方,對吧? – FWeigl

+0

嗨納丹感謝您的回答,但它沒有奏效。 Ascorbin:我想刪除/隱藏所有對象,如果沒有任何開始和包含charsequence,並顯示吐司,什麼都沒有發現。 – marson

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(); 
} 
+0

感謝您的回答,但它沒有奏效。儘管如此,當我輸入不同的字母時,其餘的都停留在同一個地方。 – marson

+0

我做了一些改進,@CSmith提出了我的建議,並將其與您的建議結合起來,並最終發揮作用。非常感謝! – marson