使用SearchView搜索RecyclerView

9

我希望能够通过RecyclerView搜索,我有一个List<BaseOfCards>(BaseOfCards是我的getter和setter类)

我的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实现Filterable接口吗?还是在* RecyclerViewAdapter *类中创建一个filter方法,然后在MainActivity中调用它?

5个回答

23

我解决了我的问题

  1. 使我的类 RecyclerViewAdapter 实现 Filterable

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

  3. RecyclerViewAdapter 中添加方法 getFilter

  4. 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();
    
        }
    }; 
    
    让MainActivity实现SearchView.OnQueryTextListener并更改onQueryTextChange方法:
    @Override
    public boolean onQueryTextChange(String newText) {
        if ( TextUtils.isEmpty ( newText ) ) {
            adapter.getFilter().filter("");
        } else {
            adapter.getFilter().filter(newText.toString());
        }
        return true;
    }
    

如果您有兴趣,它在Dev分支下:https://github.com/davideas/FlexibleAdapter/tree/dev - Davideas
这里的origitems是什么? - RevanthKrishnaKumar V.
@RevanthRev orig和items是我的物品列表,需要进行筛选。 - Ololoking
@Davidea。你的链接已经失效了。 - valerybodak
@anivaler和其他所有人:是的,实际上我已经删除了_dev_分支,因为对于库来说不再需要了。_Master_分支现在是主要参考。我仅在需要进行新开发时使用dev,就像在那个时期一样。对于不便我感到抱歉。 - Davideas
显示剩余6条评论

1
我想要补充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);

}

感谢 ololoking 的回答,它对我很有帮助。


1

search through recyclerview

在您的适配器类中扩展filterable。然后重写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;
      }

在您的主活动中添加搜索视图并将监听器添加到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


0
使用AutocompleteTextView或EditText,我按照以下方式处理了这个问题:
 public List<SalesProductsItems> mItems          

是初始的listitem实例和。

  public static List<SalesProductsItems> filteredIt 

是用于显示项目的实例。由于第一次过滤结果不为空,mItems 实例将等于 filteredIt 实例(因此丢失了初始列表),然后在 publishResults 方法中,在 mItems 失去原始值之前,我将其与传递的实例 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();
        }
    }
}

0
自从实现了另一个积极的答案后,我现在在我的FlexibleAdapter库中使用AsyncTask实现了一个快速异步过滤器,对于大型列表,性能非常好,还具有动画效果!适配器可配置以启用/禁用过滤结果中的属性,在必要时提高速度。另一个重要优点是界面仍然对用户响应。
在我的运行Android 6的三星S3上进行的测试:从开始列表10,450项,从后台进程开始到选择3,890项并过滤一个字符需要约1秒钟。
我还做了一个Wiki页面,其中包含使用适配器进行过滤的所有详细信息。

我遇到了同样的问题,你解决了这个问题吗?请@Davidea帮帮我。 - Sagar
@SagarHudge,从我之前的评论到被接受的答案的时间里,我的过滤器已经改变了,当前的过滤方式在维基页面中有描述。虽然有更好的类似Filter类的过滤器实现方式,但现在使用FlexibleAdapter是这样的。 - Davideas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接