2013-07-26 87 views
1

對於我的自定義適配器,我希望能夠過濾ListView中的項目。我實現了Filterable,並創建了一個Filter。Android:自定義過濾器不顯示結果,.clear()和.addAll()有

這裏是我的publishResults:

@Override 
protected void publishResults(CharSequence constraint, FilterResults results) 
{ 
    MainActivity.this.filteredPetList.clear(); 
    MainActivity.this.filteredPetList.addAll((ArrayList<Pet>)results.values); 

    notifyDataSetChanged(); 
} 

如果我

MainActivity.this.filteredPetList.addAll((ArrayList<Pet>)results.values); 

之後檢查filteredPetList,結果顯示正常,但該適配器將不會更新視圖。

任何想法我做錯了什麼?我可能再次做一些愚蠢的事情。

-Edit- 在我的適配器中,我重寫了notifyDataSetChanged,以查看它是否實際調用。它說:

@Override 
public void notifyDataSetChanged() 
{ 
    System.out.println("Notified..."); 
    super.notifyDataSetChanged(); 
} 

我得到的結果,每當我試圖篩選,notifyDataSetChanged被調用。我還檢查了我的filteredPetList實際上是否在Filter之外進行了更改,並且是。

這只是意見不出於某種原因更新...

CNC中添加的全適配器代碼:

private class PetAdapter extends BaseAdapter implements Filterable 
{ 
    private final Object lock = new Object(); 
    List<Row> rows; 
    ArrayList<Integer> petIds; 
    boolean clickable; 
    PetFilter petFilter; 

    public PetAdapter(ArrayList<Pet> petList, boolean clickable) 
    { 
     this.clickable = clickable; 
     rows = new ArrayList<Row>(); 
     this.petIds= new ArrayList<Integer>(); 

     for(Pet p : petList) 
     { 
      rows.add(new ImageTextTextRow(LayoutInflater.from(MainActivity.this), p.getPetImageId(), p.getPetName(), p.getPetFood())); 
      petIds.add(p.getPetId()); 
     } 
    } 

    @Override 
    public boolean isEnabled(int position) 
    { 
     //Can do that certain items ARE enabled by using the position 
     return clickable; 
    } 

    @Override 
    public int getViewTypeCount() 
    { 
     return RowType.values().length; 
    } 

    @Override 
    public int getItemViewType(int position) 
    { 
     return rows.get(position).getViewType(); 
    } 

    @Override 
    public int getCount() 
    { 
     return rows.size(); 
    } 

    @Override 
    public Object getItem(int position) 
    { 
     return rows.get(position); 
    } 

    @Override 
    public long getItemId(int position) 
    { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 
     return rows.get(position).getView(convertView); 
    } 

    /** 
    * 
    * @param position 
    * @return 
    */ 
    public int getSelectedPetId(int position) 
    { 
     return petIds.get(position); 
    } 

    @Override 
    public Filter getFilter() 
    { 
     if (petFilter == null) 
      petFilter = new PetFilter(); 

     return petFilter; 
    } 

    private class PetFilter extends Filter 
    { 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) 
     { 
      FilterResults results = new FilterResults(); 

      if (MainActivity.this.filteredPetList == null) 
      { 
       synchronized (PetAdapter.this.lock) 
       { 
        MainActivity.this.filteredPetList = new ArrayList<Pet>(MainActivity.this.originalPetList); 
       } 
      } 

      if (constraint == null || constraint.length() == 0) 
      { 
       synchronized (PetAdapter.this.lock) 
       { 
        results.values = MainActivity.this.originalPetList; 
        results.count = MainActivity.this.originalPetList.size(); 
       } 
      } 
      else 
      { 
       String constraintString = constraint.toString().toLowerCase(Locale.ENGLISH); 

       final ArrayList<Pet> items = MainActivity.this.filteredPetList; 
       final int count = items.size(); 
       final ArrayList<Pet> newItems = new ArrayList<Pet>(count); 
       for (int i = 0; i < count; i++) 
       { 
        final Pet item = items.get(i); 
        final String itemName = item.getPetName().toLowerCase(Locale.ENGLISH); 

        if (itemName.startsWith(constraintString)) 
        { 
         newItems.add(item); 
        } 
        else 
        { 
         final String[] words = itemName.split(" "); 
         final int wordCount = words.length; 
         for (int k = 0; k < wordCount; k++) 
         { 
          if (words[k].startsWith(constraintString)) 
          { 
           newItems.add(item); 
           break; 
          } 
         } 
        } 
       } 

       results.values = newItems; 
       results.count = newItems.size(); 
      } 
      return results; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) 
     { 
      MainActivity.this.filteredPetList.clear(); 
      MainActivity.this.filteredPetList.addAll((ArrayList<Pet>)results.values); 

      if (results.count > 0) 
       PetAdapter.this.notifyDataSetChanged(); 
      else 
       PetAdapter.this.notifyDataSetInvalidated(); 
     } 
    } 
} 

提前感謝!

Tregan

+0

請發佈您的適配器的完整代碼。 – Luksprog

+0

完成。添加它作爲編輯。 – Tregan

+1

這種行爲是正常的。你從'MainActivity'過濾和更新一個列表,但是你的整個適配器是基於你創建的一個全新列表'rows',所以過濾後的結果將不會被適配器看到。另外,我希望'ImageTextTextRow'不是某種行,而是將它存儲在該列表中,因爲這是一件壞事。 – Luksprog

回答

1

感謝Luksprog,我找到了一個解決方案,請參閱他對我的問題的評論。 我改變了我的適配器,現在它工作正常。我還添加了一些代碼,並進行了清理,因此與以前有所不同,但是應該清楚在閱讀Luksprog的評論和我的代碼時我改變了什麼。

private class PetAdapter extends BaseAdapter implements Filterable 
{ 
    private final Object lock = new Object(); 

    private List<Row> rows; 
    private ArrayList<Integer> petIds; 
    private boolean clickable; 
    private ArrayList<Pet> filteredPetList; 
    private PetFilter petFilter; 

    public PetAdapter(boolean clickable) 
    { 
     this.rows = new ArrayList<Row>(); 
     this.petIds = new ArrayList<Integer>(); 
     this.clickable = clickable; 
     this.filteredPetList = new ArrayList<Pet>(MainActivity.this.petList); 

     createPetRows(); 
    } 

    @Override 
    public boolean isEnabled(int position) 
    { 
     //Can do that certain items ARE enabled/disabled by using the position 
     return clickable; 
    } 

    @Override 
    public int getViewTypeCount() 
    { 
     return RowType.values().length; 
    } 

    @Override 
    public int getItemViewType(int position) 
    { 
     return rows.get(position).getViewType(); 
    } 

    @Override 
    public int getCount() 
    { 
     return rows.size(); 
    } 

    @Override 
    public Object getItem(int position) 
    { 
     return rows.get(position); 
    } 

    @Override 
    public long getItemId(int position) 
    { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) 
    { 
     return rows.get(position).getView(convertView); 
    } 

    /** 
    * Retrieve the petId for the selected row 
    * @param position the position in the list 
    * @return the petId that belongs to that row 
    */ 
    public int getSelectedPetId(int position) 
    { 
     return petIds.get(position); 
    } 

    /** 
    * Creates rows that are displayed from items in the filteredPetList 
    * Also adds petIds to a List, so that the selected pet can be found 
    */ 
    private void createPetRows() 
    { 
     //Clear all current data 
     rows.clear(); 
     petIds.clear(); 

     for(Pet p : filteredPetList) 
     { 
      rows.add(new ImageTextTextRow(LayoutInflater.from(MainActivity.this), p.getPetImageId(), p.getPetName(), p.getPetFood())); 
      petIds.add(p.getPetId()); 
     } 
    } 

    @Override 
    public Filter getFilter() 
    { 
     if (petFilter == null) 
      petFilter = new PetFilter(); 

     return petFilter; 
    } 

    /** 
    * Custom Filter for our PetAdapter 
    * @author Bas 
    * 
    */ 
    private class PetFilter extends Filter 
    { 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) 
     { 
      FilterResults results = new FilterResults(); 

      if (PetAdapter.this.filteredPetList == null) 
      { 
       synchronized (PetAdapter.this.lock) 
       { 
        PetAdapter.this.filteredPetList = new ArrayList<Pet>(MainActivity.this.petList); 
       } 
      } 

      //No constraint is sent to filter by so we're going to send back the original array 
      if (constraint == null || constraint.length() == 0) 
      { 
       synchronized (PetAdapter.this.lock) 
       { 
        results.values = MainActivity.this.petList; 
        results.count = MainActivity.this.petList.size(); 
       } 
      } 
      else 
      { 
       String constraintString = constraint.toString().toLowerCase(Locale.ENGLISH); 

       ArrayList<Pet> itemsToCheck = MainActivity.this.petList; 

       final ArrayList<Pet> newFilteredPets = new ArrayList<Pet>(itemsToCheck.size()); 
       for(Pet p : itemsToCheck) 
       { 
        final String petName = p.getPetName().toLowerCase(Locale.ENGLISH); 
        final String petFood = p.getPetFood().toLowerCase(Locale.ENGLISH); 

        // First match against the whole, non-splitted value 
        if (petName.startsWith(constraintString) || petFood.startsWith(constraintString)) 
         newFilteredPets.add(p); 
        else 
        { 
         final String[] petNameWords = petName.split(" "); 
         final String[] petFoodWords = petFood.split(" "); 
         for (String s : petNameWords) 
         { 
          if (s.startsWith(constraintString)) 
          { 
           newFilteredPets.add(p); 
           break; 
          } 
         } 
         for (String s : petFoodWords) 
         { 
          if (s.startsWith(constraintString)) 
          { 
           newFilteredPets.add(p); 
           break; 
          } 
         } 
        } 
       } 

       //Set the result 
       results.values = newFilteredPets; 
       results.count = newFilteredPets.size(); 
      } 
      return results; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) 
     { 
      //Add the results to our filteredPetList 
      PetAdapter.this.filteredPetList.clear(); 
      PetAdapter.this.filteredPetList.addAll((ArrayList<Pet>)results.values); 

      //Create rows for every filtered Pet 
      createPetRows(); 

      //Notify the Adapter 
      if (results.count > 0) 
       PetAdapter.this.notifyDataSetChanged(); 
      else 
       PetAdapter.this.notifyDataSetInvalidated(); 

      //Update the tvResults TextView with the amount of results found 
      TextView tvResults = (TextView)findViewById(R.id.tvResults); 

      if(results.count < MainActivity.this.petList.size()) 
      { 
       tvResults.setText(results.count + " results found."); 
       tvResults.setVisibility(View.VISIBLE); 
      } 
      else 
      { 
       tvResults.setText(""); 
       tvResults.setVisibility(View.GONE); 
      } 
     } 
    } 
} 
0

我只是給你我的工作自定義過濾器代碼:

public class NaamFilter extends Filter { 

    @Override 
    protected FilterResults performFiltering(CharSequence constraint) { 
     FillArray(); 
     FilterResults results = new FilterResults(); 

      List<String> filtered = new ArrayList<String>(); 
      for (String naam : namenarraylist) { 
       if(naam.toLowerCase().contains(constraint.toString().toLowerCase())) { 
        filtered.add(naam); 
       } 
      } 
      results.values = filtered; 
      results.count = filtered.size(); 
      return results; 
    } 

    @Override 
    protected void publishResults(CharSequence constraint, 
      FilterResults results) { 
     if (results.count == 0) { 
      namenarraylist.clear(); 
      notifyDataSetChanged(); 
     } else { 
      namenarraylist = (ArrayList<String>) results.values; 
      notifyDataSetChanged(); 
     } 

    } 

} 
+0

似乎沒有工作,仍然有相同的問題,列表只是不會顯示過濾結果 – Tregan

0

願你只需從你的適配器調用notifyDataSetChanged()。

+0

檢查我的編輯,我檢查了notifyDataSetChanged()被調用,它被調用就好了:/ – Tregan

相關問題