Search through RecyclerView using Searchview

早过忘川 提交于 2019-12-18 04:52:51

问题


I want to search through RecyclerView, I have List<BaseOfCards> (BaseOfCards is my getter&setter class) My RecyclerViewAdapter :

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {


private LayoutInflater inflater;
private List<BaseOfCards> items;

//private int itemLayout;
//String cardvalue;
private Activity mActivity;

public RecyclerViewAdapter(Activity mActivity, Context context, List<BaseOfCards> items) {
    this.mActivity = mActivity;
    inflater = LayoutInflater.from(context);
    this.items = items;
    //this.itemLayout = itemLayout;
}

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = inflater.inflate(R.layout.custom_row, parent, false);
    MyViewHolder holder = new MyViewHolder(view, mActivity);
    return holder;
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {

    BaseOfCards item = items.get(position);
    holder.title.setTag(item);
    holder.title.setText(item.getCardName());
}

@Override
public int getItemCount() {

    return items.size();
}

public static class MyViewHolder extends RecyclerView.ViewHolder {
    private Activity mActivity;
    TextView title;
    ImageView titileImageView;

    public MyViewHolder(View itemView, Activity mActivity) {

        super(itemView);

        titileImageView = (ImageView) itemView.findViewById(R.id.image_country);


        title = (TextView) itemView.findViewById(R.id.listText);
        this.mActivity = mActivity;

    }
}

}

I add SearchView to my menu and initialize it in MainActivity:

 MenuItem menuItem = menu.findItem(R.id.action_search1);
    searchView = (SearchView) MenuItemCompat.getActionView(menuItem);
    SearchManager manager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    searchView.setIconifiedByDefault(true);

What do I need to do next? Make my RecyclerViewAdapter implement Filterable or what? Or just make class filter in *RecyclerViewAdapter** and just call it from my MainActivity ?


回答1:


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



回答2:


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



回答3:


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.




回答4:


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.




回答5:


In your adapter class extend filterable. Then override the public Filter getFilter().

   @Override
    public Filter getFilter() {
        Filter filter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                FilterResults filterResults = new FilterResults();

                if(charSequence == null | charSequence.length() == 0){
                    filterResults.count = getUserModelListFiltered.size();
                    filterResults.values = getUserModelListFiltered;

                }else{
                    String searchChr = charSequence.toString().toLowerCase();

                    List<UserModel> resultData = new ArrayList<>();

                    for(UserModel userModel: getUserModelListFiltered){
                        if(userModel.getUserName().toLowerCase().contains(searchChr)){
                            resultData.add(userModel);
                        }
                    }
                    filterResults.count = resultData.size();
                    filterResults.values = resultData;

                }

                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {

                userModelList = (List<UserModel>) filterResults.values;
                notifyDataSetChanged();

            }
        };
        return filter;
      }

in your main activity add search view and listener to onQueryTextChange.

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

    MenuItem menuItem = menu.findItem(R.id.search_view);

    SearchView searchView = (SearchView) menuItem.getActionView();

    searchView.setMaxWidth(Integer.MAX_VALUE);

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            usersAdapter.getFilter().filter(newText);
            return true;
        }
    });



    return  true;
}

Full tutorial and source code. Recyclerview with SearchView



来源:https://stackoverflow.com/questions/28697562/search-through-recyclerview-using-searchview

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