RecyclerView过滤器不过滤

时间:2017-06-09 18:10:36

标签: android android-recyclerview

我试图在我的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();
        }
    }
}

我忘记了什么?

提前致谢!

2 个答案:

答案 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的列表保持不变。

因此,请将适配器更改为始终使用已过滤的列表。