代码之家  ›  专栏  ›  技术社区  ›  user6677716

如何在回收器视图中正确执行搜索

  •  0
  • user6677716  · 技术社区  · 7 年前

    我有一个RecyclerView,它使用领域数据库获取数据,我想在操作栏上实现一个SearchView,可以搜索RecyclerView的项目,这是我的代码,但我似乎无法让它工作。

    这是菜单XML

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/action_search"
        android:icon="@drawable/ic_search_white_24dp"
        android:title="Search"
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="ifRoom"/>
    <item android:id="@+id/action_add"
        android:icon="@drawable/ic_add_white_48dp"
        android:title="Add"
        app:showAsAction="ifRoom"/>
    

    在活动中选择的OnOptions项

    public boolean onOptionsItemSelected(MenuItem item) {
        // Take appropriate action for each action item click
        switch (item.getItemId()) {
            case R.id.action_search:
                // search action
                SearchView searchView=(SearchView)item.getActionView();
                searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String query) {
                        //adapter.getFilter().filter(query);
                        return false;
                    }
    
                    @Override
                    public boolean onQueryTextChange(String newText) {
                        //adapter.getFilter().filter(newText);
                        newText=newText.toLowerCase();
                        System.out.println(results);
                        ArrayList<UserInfo> newList=new ArrayList<>();
                        for (UserInfo userInfo : results){
                            String username=userInfo.getUsername().toLowerCase();
                            String password=userInfo.getPassword().toLowerCase();
                            String type=userInfo.getType().toLowerCase();
                            if (username.contains(newText)||password.contains(newText)||type.contains(newText)){
                                newList.add(userInfo);
                            }
                        }
                        adapter.setFilter(newList);
                        return true;
                    }
                });
                return true;
            case R.id.action_add:
                addInfo();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    

    我的适配器类

    public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder> {
    private LayoutInflater layoutInflater;
    java.util.List<UserInfo> data= Collections.emptyList();
    ArrayList<UserInfo> arrayList;
    public Adapter(Context context, java.util.List<UserInfo> data){
        layoutInflater=LayoutInflater.from(context);
        this.data=data;
    }
    
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view=layoutInflater.inflate(R.layout.list_item , parent,false);
        MyViewHolder holder=new MyViewHolder(view);
        return holder;
    }
    
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        UserInfo current=data.get(position);
        holder.username.setText("Username: "+current.username);
        holder.password.setText("Password: "+current.password);
        holder.type.setText("Type: "+current.type);
    }
    
    @Override
    public int getItemCount() {
        return data.size();
    }
    
    class MyViewHolder extends RecyclerView.ViewHolder{
        TextView username,password,type;
        public MyViewHolder(View itemView) {
            super(itemView);
            username= (TextView) itemView.findViewById(R.id.username_TV);
            password= (TextView) itemView.findViewById(R.id.password_TV);
            type= (TextView) itemView.findViewById(R.id.type_TV);
        }
    }
    public void setFilter(List<UserInfo> newList){
        arrayList=new ArrayList<>();
        arrayList.addAll(newList);
        notifyDataSetChanged();
    }
    

    }

    6 回复  |  直到 7 年前
        1
  •  2
  •   user6677716 user6677716    7 年前

    这就是我问题的解决方案 首先在onCreateOptions菜单中添加

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_actions, menu);
        MenuItem search=menu.findItem(R.id.action_search);
    
        //this 2 lines
        SearchView searchView=(SearchView)search.getActionView();
        search(searchView);
    
        return super.onCreateOptionsMenu(menu);
    }
    

    搜索方法

    private void search(SearchView searchView) {
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }
    
            @Override
            public boolean onQueryTextChange(String newText) {
                newText=newText.toLowerCase();
                ArrayList<UserInfo> newList=new ArrayList<>();
                for (UserInfo userInfo : results){
                    String username=userInfo.getUsername().toLowerCase();
                    String password=userInfo.getPassword().toLowerCase();
                    String type=userInfo.getType().toLowerCase();
                    if (username.contains(newText)||password.contains(newText)||type.contains(newText)){
                        newList.add(userInfo);
                    }
                }
                adapter.setFilter(newList);
                return true;
            }
        });
    }
    

    在适配器上写入的setFilter方法

    public void setFilter(List<UserInfo> newList){
        data=new ArrayList<>();
        data.addAll(newList);
        notifyDataSetChanged();
    }
    
        2
  •  1
  •   Anand Diamond    7 年前

    我希望这个答案能帮助你Mahmoud Omara

    你好,马哈茂德·奥马拉,你在使用领域数据库吗。

    在Recyclerview adapter中实现Filterable,然后生成@Override方法getFilter。

    然后实现自己的过滤器,就像我已经更改了适配器一样

    public class Adapter extends RecyclerView.Adapter<Adapter.MyViewHolder>  implements Filterable {
    private LayoutInflater layoutInflater;
    java.util.List<UserInfo> data= Collections.emptyList();
    public Adapter(Context context, java.util.List<UserInfo> data){
        layoutInflater=LayoutInflater.from(context);
        this.data=data;
    }
    
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view=layoutInflater.inflate(R.layout.list_item , parent,false);
        MyViewHolder holder=new MyViewHolder(view);
        return holder;
    }
    
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        UserInfo current=data.get(position);
        holder.username.setText("Username: "+current.username);
        holder.password.setText("Password: "+current.password);
        holder.type.setText("Type: "+current.type);
    }
    
    @Override
    public int getItemCount() {
        return data.size();
    }
    
    class MyViewHolder extends RecyclerView.ViewHolder{
        TextView username,password,type;
        public MyViewHolder(View itemView) {
            super(itemView);
            username= (TextView) itemView.findViewById(R.id.username_TV);
            password= (TextView) itemView.findViewById(R.id.password_TV);
            type= (TextView) itemView.findViewById(R.id.type_TV);
        }
    }
    
    @Override
    public Filter getFilter() {
        return new MyNamesFilter();
    }
    private class MyNamesFilter
            extends Filter {
    
    
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            return new FilterResults();
        }
    
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
    
            //myRealm is your realm object
            //contactName is in your database column name  replace your table name column
    
            RealmResults<Contact> contactArrayLisst = myRealm.where(Contact.class)
                    .beginGroup()
                    .contains("contactName", constraint.toString(), Case.INSENSITIVE)
                    .endGroup()
                    .findAll();
            data.clear();
            data.addAll(contactArrayLisst);
            notifyDataSetChanged();
    
    
        }
    }
    }
    

    然后在QueryTextChange方法上更改活动类

    像这样

     adapter.getFilter().filter(s);
    
        3
  •  0
  •   Akhil    7 年前

    看起来你在用 阵列列表 代替 数据 在您的 设置筛选器 方法,使用 数据 相反

        4
  •  0
  •   Richard Kamere    5 年前

    在适配器类上实现filterable。 重写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;
        }
    

    在主要活动中,创建searchview并对querytextchange执行筛选。

      @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

        5
  •  0
  •   Suraj Bahadur    4 年前

    希望这个答案能有所帮助。

    首先,您需要创建两个 ArrayList oriList 保留原始列表并 modList 保留过滤后的数据。

    private ArrayList<SingleData> modList;
    private ArrayList<SingleData> original;
    

    1. constructer 或者在适配器中创建一个方法来设置值,如下所示

    public void setEmployees(ArrayList<SingleData> dataList) {
            this.dataList = new ArrayList<>();
            this.dataList = dataList;
            oriDataList = new ArrayList<>();
            oriDataList = (ArrayList<SingleData>) dataList.clone(); 
            notifyDataSetChanged();
        }
    

    **注:**1。如果不想更改原始列表数据,请使用 clone() 方法添加新列表时。

    2. 创建了另一个将处理搜索查询的方法:

       public void filter(String text) {
            dataList.clear();
            if (text.isEmpty()) {
                dataList.addAll(oriDataList);
            } else {
                text = text.toLowerCase();
                for (SingleData item : oriDataList) {
                    if (item.getName().toLowerCase().contains(text)) {
                        dataList.add(item);
                    }
                }
            }
            notifyDataSetChanged();
        }
    

    3. 从下面的活动或片段调用搜索方法

      YOUR_ADAPTER_OBJECT.filter(PASS_SEARCH_TEXT_HERE);
    

    4. SingleData 是pojo类

    public class SingleData{
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
        6
  •  0
  •   Google Devotted    4 年前
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                return true;
            }
    
            @Override
            public boolean onQueryTextChange(String s) {
    
                searchKeyword = s;
                s=s.toLowerCase();
                ArrayList<GetGoogleTemplesResponse.ResultsBean> temples=new ArrayList<>();
                for (GetGoogleTemplesResponse.ResultsBean bean : results){
                    String templeName=bean.getName().toLowerCase();
                    if (templeName.contains(s)){
                        temples.add(bean);
                    }
                }
                adapter.setFilter(temples);
    
                return true;
            }
        });
    

    In适配器

     public void setFilter(List<GetGoogleTemplesResponse.ResultsBean> list){
        beans=new ArrayList<>();
        beans.addAll(list);
        notifyDataSetChanged();
    }