我试图在我的RecyclerView中实施搜索过滤器,就像在this post中一样
我已对其进行了调试,并按预期过滤了这些项目,但该列表在应用程序中似乎没有变化。 I.E。:我过滤一个名称,有7个结果,在屏幕上它是原始列表。
我对活动的onCreateMenuOptions是:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override public boolean onQueryTextSubmit(String filterString) {
adapter.getFilter().filter(filterString);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
return true;
}
我的适配器看起来像这样:
public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHolder> implements INameableAdapter {
private List<Anime> items;
private List<Anime> filteredItems;
private AnimeFilter animeFilter;
final private Context context;
@Override
public Character getCharacterForElement(int element) {
Character c = items.get(element).getTitle().charAt(0);
if(Character.isDigit(c)){
c = '#';
}
return c;
}
public static class AnimeViewHolder extends RecyclerView.ViewHolder {
// Campos respectivos de un item
final public ImageView img;
final public TextView title;
public AnimeViewHolder(View v) {
super(v);
img = (ImageView) v.findViewById(R.id.image);
title = (TextView) v.findViewById(R.id.title);
}
}
public AnimeAdapter(List<Anime> items, Context context) {
this.items = items;
this.context = context;
this.filteredItems = new ArrayList<>();
}
@Override
public int getItemCount() {
return items.size();
}
@Override
public AnimeViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.anime_card, viewGroup, false);
return new AnimeViewHolder(v);
}
@Override
public void onBindViewHolder(AnimeViewHolder viewHolder, int i) {
if (BuildConfig.DEBUG) {
//This is made to check if the image cache is working as expected.
Picasso.with(context).setIndicatorsEnabled(true);
Picasso.with(context).setLoggingEnabled(true);
}
final int position = i;
final ImageView imageView = viewHolder.img;
Picasso.with(context)
.load(items.get(i).getImageUrl())
.into(imageView);
viewHolder.title.setText(items.get(i).getTitle());
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
Intent intent = new Intent(context, TabActivity.class);
Bundle b = new Bundle();
b.putString("title", items.get(position).title);
b.putString("playlist", items.get(position).playlist);
imageView.buildDrawingCache();
Bitmap image = imageView.getDrawingCache();
b.putParcelable("imageBitmap", image);
intent.putExtras(b);
v.getContext().startActivity(intent);
}
});
}
public Filter getFilter() {
if(animeFilter == null)
animeFilter = new AnimeFilter(this, items);
return animeFilter;
}
private static class AnimeFilter extends Filter {
private final AnimeAdapter adapter;
private final List<Anime> originalList;
private final List<Anime> filteredList;
private AnimeFilter(AnimeAdapter adapter, List<Anime> 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.length() == 0) {
filteredList.addAll(originalList);
} else {
final String filterPattern = constraint.toString().toLowerCase().trim();
for (final Anime anime : originalList) {
if (anime.getTitle().toLowerCase().contains(filterPattern)) {
filteredList.add(anime);
}
}
}
results.values = filteredList;
results.count = filteredList.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
adapter.filteredItems.clear();
adapter.filteredItems.addAll((ArrayList<Anime>) results.values);
adapter.notifyDataSetChanged();
}
}
}
我忘记了什么?
提前致谢!
答案 0 :(得分:3)
我对您的代码进行了一些更改。
检查一下:
public class AnimeAdapter extends RecyclerView.Adapter<AnimeAdapter.AnimeViewHolder> implements INameableAdapter {
private List<Anime> items;
private List<Anime> filteredItems;
private AnimeFilter animeFilter;
final private Context context;
@Override
public Character getCharacterForElement(int element) {
Character c = items.get(element).getTitle().charAt(0);
if(Character.isDigit(c)){
c = '#';
}
return c;
}
public static class AnimeViewHolder extends RecyclerView.ViewHolder {
// Campos respectivos de un item
final public ImageView img;
final public TextView title;
public AnimeViewHolder(View v) {
super(v);
img = (ImageView) v.findViewById(R.id.image);
title = (TextView) v.findViewById(R.id.title);
}
}
public AnimeAdapter(List<Anime> items, Context context) {
this.items = items;
this.context = context;
this.filteredItems = new ArrayList<>();
// we copy the original list to the filter list and use it for setting row values
this.filteredItems.addAll(items);
}
@Override
public int getItemCount() {
return filteredItems.size();//you must always return count of filtered rows
}
@Override
public AnimeViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.anime_card, viewGroup, false);
return new AnimeViewHolder(v);
}
@Override
public void onBindViewHolder(AnimeViewHolder viewHolder, int i) {
if (BuildConfig.DEBUG) {
//This is made to check if the image cache is working as expected.
Picasso.with(context).setIndicatorsEnabled(true);
Picasso.with(context).setLoggingEnabled(true);
}
final int position = i;
final ImageView imageView = viewHolder.img;
Picasso.with(context)
.load(filteredItems.get(i).getImageUrl())//we you filteredItems instead of items
.into(imageView);
viewHolder.title.setText(filteredItems.get(i).getTitle());
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
Intent intent = new Intent(context, TabActivity.class);
Bundle b = new Bundle();
b.putString("title", filteredItems.get(position).title);
b.putString("playlist", filteredItems.get(position).playlist);
imageView.buildDrawingCache();
Bitmap image = imageView.getDrawingCache();
b.putParcelable("imageBitmap", image);
intent.putExtras(b);
v.getContext().startActivity(intent);
}
});
}
public Filter getFilter() {
if(animeFilter == null)
animeFilter = new AnimeFilter(this, items);
return animeFilter;
}
private static class AnimeFilter extends Filter {
private final AnimeAdapter adapter;
private final List<Anime> originalList;
private final List<Anime> filteredList;
private AnimeFilter(AnimeAdapter adapter, List<Anime> 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.length() == 0) {
filteredList.addAll(originalList);
} else {
final String filterPattern = constraint.toString().toLowerCase().trim();
for (final Anime anime : originalList) {
if (anime.getTitle().toLowerCase().contains(filterPattern)) {
filteredList.add(anime);
}
}
}
results.values = filteredList;
results.count = filteredList.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
adapter.filteredItems.clear();
adapter.filteredItems.addAll((ArrayList<Anime>) results.values);
adapter.notifyDataSetChanged();
}
}
}
答案 1 :(得分:2)
问题是,您使用RecyclerView
列表中的项目而不是items
填充了filteredItems
。
在您的过滤器中,您只更新filteredItems
列表并通知适配器某些内容已更改。但事实上,适配器用于填充RecyclerView
的列表保持不变。
因此,请将适配器更改为始终使用已过滤的列表。