Search through RecyclerView using Searchview

五迷三道 提交于 2019-11-29 06:57:06
Ololoking

I solved my problem

  1. Make my class RecyclerViewAdapter implements Filterable

  2. Add line private List<BaseOfCards> orig;

  3. Add method getFilter in RecyclerViewAdapter

    public Filter getFilter() {
    return new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            final FilterResults oReturn = new FilterResults();
            final List<BaseOfCards> results = new ArrayList<BaseOfCards>();
            if (orig == null)
                orig  = items;
                if (constraint != null){
                    if(orig !=null & orig.size()>0 ){
                        for ( final BaseOfCards g :orig) {
                            if (g.getCardName().toLowerCase().contains(constraint.toString()))results.add(g);
                        }
                    }
                    oReturn.values = results;
                }
                return oReturn;
            }
    
    @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            items = (ArrayList<BaseOfCards>)results.values;
            notifyDataSetChanged();
    
        }
    }; 
    
  4. Make MainActivity implements SearchView.OnQueryTextListener and change method onQueryTextChange :

    @Override
    public boolean onQueryTextChange(String newText) {
        if ( TextUtils.isEmpty ( newText ) ) {
            adapter.getFilter().filter("");
        } else {
            adapter.getFilter().filter(newText.toString());
        }
        return true;
    }
    

Using an autocompletetextview or an edittext i handled this one as following where

 public List<SalesProductsItems> mItems          

is the initial listitem instance and .

  public static List<SalesProductsItems> filteredIt 

is the instance used in displaying items.Since the 1st time the filter results is not null the mItems instance will be equal to the filteredIt instance (thus loosing the initial list) then on the publishResults method right before mItems looses the original values, I'm equating it to the passed instance originallist . Hope it helps someone

private static class ProductsFilter extends Filter {

    private final SalesProductsAdapter adapter;

    private final List<SalesProductsItems> originalList;

    private final List<SalesProductsItems> filteredList;

    private ProductsFilter(SalesProductsAdapter adapter, List<SalesProductsItems> 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 == null || constraint.length() == 0)
            filteredList.addAll(originalList);
        else {
            final String filterPattern = constraint.toString().toLowerCase().trim();

            for (final SalesProductsItems it : originalList) {

                if (it.getProduct().toLowerCase().contains(filterPattern)) {
                    filteredList.add(it);
                }
            }
        }

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

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        adapter.mItems = originalList;
        if(results.count > 0) {
            filteredIt.clear();
            filteredIt.addAll((ArrayList<SalesProductsItems>) results.values);
            adapter.notifyDataSetChanged();
        } else {
            filteredIt.clear();
            filteredIt.addAll(adapter.mItems);
            adapter.notifyDataSetChanged();
        }
    }
}
Leontsev Anton

I want to add to ololoking answer. In MainActivity we should also add next code so it would work:

   @Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_layout, menu);

    MenuItem searchItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView.setIconifiedByDefault(true);
    searchView.setOnQueryTextListener(this);
    return super.onCreateOptionsMenu(menu);

}

Thanks ololoking for your answer. It helped me.

From the time the other positive answer was done, I've now implemented a fast async filter using AsyncTask in my FlexibleAdapter library, performance are very good with big lists, having animations too! The Adapter is configurable to enable/disable properties in filtering result to increase speed when necessary. Another big advantage is also that interface is still responding to the user.

Test done in my Samsung S3 running Android 6: with a starting list of 10.450 items, from the moment the background process starts it takes ~1s to filter a character and select 3.890 items.

I've done also a Wiki page with all the details to use filter with the Adapter.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!