如何正确地在Recycler View中实现搜索

时间:2018-01-05 01:29:47

标签: android android-studio android-recyclerview realm searchview

我有一个使用Realm数据库获取数据的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"/>

活动

中的onOptionsItemSelected
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 个答案:

答案 0 :(得分:2)

这是我的问题的解决方案 首先在onCreateOptionsMenu上添加此

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

答案 1 :(得分:0)

您似乎在 setFilter 方法中使用 arrayList 而非数据,请使用数据代替< / p>

答案 2 :(得分:0)

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

你好Mahmoud Omara你在使用领域数据库。

在Recyclerview适配器中实现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)

可在您的适配器类上过滤的实现。 覆盖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;
    }

在您的主要活动中,创建您的搜索视图并对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

答案 4 :(得分:0)

希望这个答案对您有帮助。

首先,您需要创建两个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;
    }
}

答案 5 :(得分:0)

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

在适配器中

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