使用 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 中调用它?
我解决了我的问题
制作我的classRecyclerViewAdapterimplements Filterable
添加行private List<BaseOfCards> orig;
在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();
}
};
创建 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
我想搜索 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 中调用它?
我解决了我的问题
制作我的classRecyclerViewAdapter
implements Filterable
添加行
private List<BaseOfCards> orig;
在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(); } };
创建 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