Add a search filter on RecyclerView with Cards?

前端 未结 3 2147
悲&欢浪女
悲&欢浪女 2020-11-28 05:17

I found solutions for filters on ListView and SearchView on RecyclerView separately, but I wish to combine them. Is it even possible?<

相关标签:
3条回答
  • 2020-11-28 05:53

    Yes it is possible Your RecyclerView.Adapter can implement Filterable. After that you have to override Filter getFilter() method.

    You have to define your own filter as is shown in the code below:

    @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)
            }
    }
    

    Example

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

    After that in the place when you want to filtering call:

    userListAdapter.getFilter().filter(text)
    
    0 讨论(0)
  • 2020-11-28 05:53

    Inside Fragment Class declare that:

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

    then inside onCreate add same source destination to both dataSet ant dataOrigin

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

    Finally use the magic function:

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

    Notice User is the list content you can replace with your Object have fun :)

    0 讨论(0)
  • 2020-11-28 05:57

    Here is complete sample code

    Model Class

    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 Activity Use

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

    Then Filter

    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());
            }
        });
    
    0 讨论(0)
提交回复
热议问题