使用 Searchview 搜索 RecyclerView

Search through RecyclerView using Searchview

我想搜索 RecyclerView,我有 List<BaseOfCards>(BaseOfCards 是我的 getter&setter class) 我的 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;

    }
}

}

我将 SearchView 添加到我的菜单并在 MainActivity 中初始化它:

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

接下来我需要做什么?让我的 RecyclerViewAdapter implement Filterable 或者什么?或者只是在 *RecyclerViewAdapter** 中创建 class filter 并从我的 MainActivity 中调用它?

我解决了我的问题

  1. 制作我的classRecyclerViewAdapterimplements Filterable

  2. 添加行private List<BaseOfCards> orig;

  3. RecyclerViewAdapter

    中添加方法getFilter
    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. 创建 MainActivity implements SearchView.OnQueryTextListener 并更改方法 onQueryTextChange :

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

使用 autocompletetextview 或 edittext 我按以下方式处理了这个

 public List<SalesProductsItems> mItems          

是初始列表项实例,并且 .

  public static List<SalesProductsItems> filteredIt 

是用于显示 items.Since 的实例,第一次过滤结果不为空 mItems 实例将等于 filteredIt 实例(因此丢失初始列表)然后在 mItems 丢失原始值之前的 publishResults 方法上,我将其等同于传递的实例 originallist 。希望对某人有所帮助

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

我想添加到 ololoking 答案中。 在 MainActivity 中,我们还应该添加下一个代码,这样它才能工作:

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

}

感谢 ololking 的回答。它帮助了我。

从另一个肯定的答案完成后,我现在已经在我的 FlexibleAdapter 库中使用 AsyncTask 实现了一个 快速异步过滤器 ,性能非常适合大列表,也有动画! 适配器可配置为过滤结果中的 enable/disable 属性,以在必要时提高速度。另一个很大的优势是界面仍在响应用户。

在我的 Samsung S3 上完成的测试 运行 Android 6:起始列表有 10.450 个项目,从后台进程启动的那一刻起,过滤一个字符需要大约 1 秒,select 3.890 件商品。

我还完成了 Wiki page 的所有详细信息,以便将过滤器与适配器一起使用。

在您的适配器中 class 扩展可过滤。 然后覆盖 public 过滤器 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;
      }

在您的主 activity 中将搜索视图和侦听器添加到 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;
}

完整教程和源代码。 Recyclerview with SearchView