2015-04-22 8 views

Antwort

77

Ja, es ist möglich Ihre RecyclerView.Adapter kann Filterable implementieren. Danach müssen Sie die Methode Filter getFilter() überschreiben.

Sie haben einen eigenen Filter zu definieren, wie in den folgenden Code dargestellt:

@Override 
public Filter getFilter() { 
    return new YourFilterClass(); 
} 

YourFilterClass

class YourFilterClass extends Filter { 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      //Here you have to implement filtering way 
      final FilterResults results = new FilterResults(); 
      //logic to filtering 
      results.values = ... 
      results.count = ... 
      return results; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      // here you can use result - (f.e. set in in adapter list) 
     } 
} 

Beispiel

public class UserListAdapter extends RecyclerView.Adapter<UserListAdapter.ViewHolder> implements Filterable { 

    private final List<User> userList; 

    private final List<User> filteredUserList; 

    private UserFilter userFilter; 

    public UserListAdapter(Context context) { 
     this.userList =new ArrayList<>(); 
     this.filteredUserList = new ArrayList<>(); 
    } 


    ///... other methods 

    @Override 
    public Filter getFilter() { 
     if(userFilter == null) 
      userFilter = new UserFilter(this, userList); 
     return userFilter; 
    } 

    private static class UserFilter extends Filter { 

     private final UserListAdapter adapter; 

     private final List<User> originalList; 

     private final List<User> filteredList; 

     private UserFilter(UserListAdapter adapter, List<User> originalList) { 
      super(); 
      this.adapter = adapter; 
      this.originalList = new LinkedList<>(originalList); 
      this.filteredList = new ArrayList<>(); 
     } 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      filteredList.clear(); 
      final FilterResults results = new FilterResults(); 

      if (constraint.length() == 0) { 
       filteredList.addAll(originalList); 
      } else { 
       final String filterPattern = constraint.toString().toLowerCase().trim(); 

       for (final User user : originalList) { 
        if (user.getName().contains(filterPattern)) { 
         filteredList.add(user); 
        } 
       } 
      } 
      results.values = filteredList; 
      results.count = filteredList.size(); 
      return results; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      adapter.filteredUserList.clear(); 
      adapter.filteredUserList.addAll((ArrayList<User>) results.values); 
      adapter.notifyDataSetChanged(); 
     } 
    } 
} 

Danach an der Stelle, wenn Sie möchten filtern Anruf:

userListAdapter.getFilter().filter(text) 
+1

Filter Ja auf die Idee kam. Gibt es dafür ein gutes Beispiel? – Ryan

+0

RecyclerView unterstützt keine Out-of-the-Box-Filterung, imho – pskink

+0

@pskink Soweit ich weiß nein. Adapter von 'RecyclerView' ist ein' public static abstract class Adapter {'Vielleicht gibt es einen Mechanismus, aber ich weiß es nicht. Meine Lösung funktioniert :) –

3

Innerhalb Fragment Class erklären:

protected List<User> mDataset; 
protected List<User> mDataOrigin; 

dann in onCreate gleiche Quelle Ziel ant sowohl dataSet dataOrigin

mDataset = getObjectsFromDB(); 
mDataOrigin = getObjectsFromDB(); 

schließlich die magische Funktion hinzufügen:

private void filterRecyclerView(String charText){ 
    charText = charText.toLowerCase(); 
    clearDataSet(); 
    if (charText.length() == 0) { 
     mDataset.addAll(mDataOrigin); 
    } else { 
     for (User user : mDataOrigin) { 
      if (user.getName().toLowerCase().contains(charText)) { 
       mDataset.add(user); 
      } 
     } 
    } 
    mAdapter.notifyDataSetChanged(); 
} 

Hinweis User ist die Liste Inhalt, den Sie mit Ihrem Objekt haben Spaß ersetzen können :)

+0

danke Mann, es rette mich eine Menge –

+0

zukünftige Leser stellen sicher, dass Sie nicht vergessen 'mDataset = getObjectsFromDB(); mDataOrigin = getObjectsFromDB(); 'um von der Quelle selbst zu setzen oder das mDataset zu klonen, da ich einige Stunden damit verbracht habe, das Problem zu untersuchen, indem ich' mDataOrigin = mDataset', P.S. 'mDataOrigin = mDataset.clone()' funktionierte gut für mich, wenn du db/func call nicht drücken willst – Anup

1

Hier vollständige Beispielcode

Model-Klasse

public class Skills { 

    int id; 
    String skill; 
    boolean isSelected; 

    public boolean isSelected() { 
     return isSelected; 
    } 

    public void setSelected(boolean selected) { 
     isSelected = selected; 
    } 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public String getSkill() { 
     return skill; 
    } 

    public void setSkill(String skill) { 
     this.skill = skill; 
    } 
} 

Adapter Class

private static final String TAG = SkillAdapter.class.getSimpleName(); 
    protected List<Skills> mOriginalData = new ArrayList<>(); 
    protected List<Skills> mResultData = new ArrayList<>(); 

    protected Activity mActivity; 
    OnRecyclerViewClick onRecyclerViewClick; 
    private ItemFilter mFilter = new ItemFilter(); 

    public SkillAdapter(Activity activity, OnRecyclerViewClick onRecyclerViewClick) { 
     mActivity = activity; 
     this.onRecyclerViewClick = onRecyclerViewClick; 
    } 

    @Override 
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 

     View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_skill, 
       parent, false); 

     return new ViewHolder(view); 
    } 

    @Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 

     final Skills data = mResultData.get(position); 
     try { 
      final ViewHolder viewHolder = (ViewHolder) holder; 

      if (data != null) { 
       viewHolder.checkSkill.setText(data.getSkill()); 
       viewHolder.checkSkill.setChecked(data.isSelected()); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public int getItemCount() { 
     return mResultData.size(); 
    } 

    public void addItem(Skills exam) { 
     mOriginalData.add(exam); 
     mResultData.add(exam); 
     int index = mOriginalData.indexOf(exam); 
     notifyItemInserted(index); 
    } 

    public void removeItem(int index) { 
     mOriginalData.remove(index); 
     notifyItemRemoved(index); 
    } 

    public void removeItem(Skills exam) { 
     int index = mOriginalData.indexOf(exam); 
     mOriginalData.remove(exam); 
     notifyItemRemoved(index); 
    } 

    public Filter getFilter() { 
     return mFilter; 
    } 


    public Skills getItem(int index) { 
     return mOriginalData.get(index); 
    } 

    public void replaceItem(int index, Skills audioMeta) { 
     mOriginalData.set(index, audioMeta); 
     notifyItemChanged(index); 
    } 

    public class ViewHolder extends RecyclerView.ViewHolder { 

     CheckBox checkSkill; 

     public ViewHolder(View itemView) { 
      super(itemView); 

      checkSkill = (CheckBox) itemView.findViewById(R.id.chkSkill); 
      checkSkill.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View v) { 
        onRecyclerViewClick.onItemClick(v, getLayoutPosition()); 
       } 
      }); 
     } 
    } 


    private class ItemFilter extends Filter { 

     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 

      String filterString = constraint.toString().toLowerCase(); 

      FilterResults results = new FilterResults(); 

      int count = mOriginalData.size(); 

      final ArrayList<Skills> tempFilterList = new ArrayList<Skills>(count); 

      String filterableString; 

      for (int i = 0; i < count; i++) { 
       filterableString = mOriginalData.get(i).getSkill(); 
       if (filterableString.toLowerCase().contains(filterString)) { 
        tempFilterList.add(mOriginalData.get(i)); 
       } 
      } 

      results.values = tempFilterList; 
      results.count = tempFilterList.size(); 

      return results; 
     } 

     @SuppressWarnings("unchecked") 
     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      mResultData.clear(); 
      mResultData = (ArrayList<Skills>) results.values; 
      notifyDataSetChanged(); 
     } 
    } 

In Aktivität Verwenden

mAdapter = new SkillAdapter(SkillsActivity.this, SkillsActivity.this); 
    recyclerView.setLayoutManager(new LinearLayoutManager(mContext)); 
    recyclerView.setAdapter(mAdapter); 

Dann

editSearch.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 

     } 

     @Override 
     public void afterTextChanged(Editable s) { 
      mAdapter.getFilter().filter(editSearch.getText().toString()); 
     } 
    });