【问题标题】:How to hide items from recyclerview as I search in a List<>当我在列表中搜索时如何隐藏 recyclerview 中的项目<>
【发布时间】:2016-09-12 15:47:37
【问题描述】:

我正在使用 recyclerView 来显示电影海报网格。海报包含在 List 中以及它们各自的标题等。

我实现了一个 searchView 小部件,我可以成功地获得一个匹配结果列表。但我不能隐藏其他的。

如您所知,我不想从适配器中删除不相关的电影,否则用户将无法再次看到它们。

这是代码:

public class SearchUtils {

    public static List<String> search(List<Show> list, String keyword){
        List<String> results = new ArrayList<>();

        for (Show curVal : list){
            String curTitle = curVal.getTitle().toLowerCase().trim();
            if (curTitle.contains(keyword)){
                results.add(curTitle);
            }else{
                results = new ArrayList<>();
            }
        }
        return results;

    }
}

ListFragment.java

public class ListFragment extends Fragment implements LoaderManager.LoaderCallbacks<List<Show>> {
    private static final String LOG_TAG = "ListFragment";
    private static final String ARG_SCOPE = "com.dcs.shows.activity_to_launch";
    private static final String BASE_URL = "http://api.themoviedb.org/3";
    private TextView tv;
    private ProgressBar pb;
    private int scope;
    private RecyclerView mRecyclerView;
    private ShowAdapter mShowAdapter;
    private SearchView mSearchView;


    public static ListFragment newInstance(int target) {
        Bundle args = new Bundle();
        args.putInt(ARG_SCOPE, target);
        ListFragment fragment = new ListFragment();
        fragment.setArguments(args);
        return fragment;
    }

    public ListFragment() {
    }



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        scope = getArguments().getInt(ARG_SCOPE);
        setHasOptionsMenu(true);
        Log.i(LOG_TAG, "onCreate@Scope is: " + scope);
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_list, container, false);

        mShowAdapter = new ShowAdapter(new ArrayList<Show>());
        mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
        GridLayoutManager glm = new GridLayoutManager(getActivity(), 4);
        mRecyclerView.setLayoutManager(glm);
        mRecyclerView.addItemDecoration(new SpacesItemDecoration(8, getActivity()));
        mRecyclerView.setAdapter(mShowAdapter);
        mRecyclerView.addOnScrollListener(new EndlessRecyclerViewScrollListener(glm) {
            @Override
            public void onLoadMore(int page, int totalItemsCount) {
                // Triggered only when new data needs to be appended to the list
                // Add whatever code is needed to append new items to the bottom of the list
            }
        });

        pb = (ProgressBar)rootView.findViewById(R.id.progress_view);

        ConnectivityManager connMgr = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            // fetch data
            getLoaderManager().initLoader(1, null, this);
        } else {
            // display error
            pb.setVisibility(View.GONE);

        }

        return rootView;
    }



    List<Show> searchList;

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);


        getActivity().getMenuInflater().inflate(R.menu.main, menu);
        final MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
        mSearchView = (SearchView) myActionMenuItem.getActionView();
        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String s) {
                if(!mSearchView.isIconified()) {
                    mSearchView.setIconified(true);
                }
                myActionMenuItem.collapseActionView();
                return false;
            }
            @Override
            public boolean onQueryTextChange(String s) {
                if(s != null || !s.isEmpty()) {
                    for(Show movie : mShowAdapter.getList()) {
                        if(movie.getTitle().toLowerCase().contains(s.toLowerCase())){
                            mShowAdapter.add(movie);
                        }
                        mShowAdapter.notifyDataSetChanged();
                    }
                } else {
                    mShowAdapter.addItemsToList(searchList, false);
                }
                return false;
            }

        });
        mSearchView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {

            @Override
            public void onViewDetachedFromWindow(View arg0) {
                // search was detached/closed
                Log.v(LOG_TAG, "Restoring list: " + searchList + " size: " + searchList.size());
                mShowAdapter.addItemsToList(searchList, false);
            }

            @Override
            public void onViewAttachedToWindow(View arg0) {
                // search was opened
                searchList = mShowAdapter.getList();
            }
        });
    }







    private class ShowHolder extends RecyclerView.ViewHolder {
        public ImageView mImageView;
        public TextView mTextView;

        public ShowHolder(View itemView) {
            super(itemView);
            mImageView = (ImageView) itemView.findViewById(R.id.grid_item_image);
            mTextView = (TextView) itemView.findViewById(R.id.grid_item_title);
        }

    }

    private class ShowAdapter extends RecyclerView.Adapter<ShowHolder> {
        private List<Show> mShows;

        public ShowAdapter(List<Show> shows) {
            mShows = shows;
        }
        public void add(Show show){
            mShows.add(show);
            notifyDataSetChanged();
        }
        public void addItemsToList(List<Show> newShows, boolean append){
            if(append){
                mShows.addAll(newShows);
            }else {
                mShows = newShows;
            }
            notifyDataSetChanged();
        }

        public void removeItemsFromList(int index){
            mShows.remove(index);
            notifyItemRemoved(index);
        }


        public List<Show> getList(){
            return mShows;
        }

        @Override
        public ShowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            LayoutInflater inflater = LayoutInflater.from(getActivity());
            View rootView = inflater.inflate(R.layout.list_item_row, parent, false);
            return new ShowHolder(rootView);
        }
        @Override
        public void onBindViewHolder(ShowHolder holder, int position) {
            Show currentShow = mShows.get(position);

            holder.mTextView.setText(currentShow.getTitle());
            Glide.with(getActivity()).load(currentShow.getImage()).into(holder.mImageView);

        }
        @Override
        public int getItemCount() {
            return mShows.size();
        }
    }



    @Override
    public Loader<List<Show>> onCreateLoader(int i, Bundle bundle) {
        //start the loader with the appropriate uri
        //for now it only supports movies+popular
        //it will support movies+top, tv+popular, tv+top.
        Uri baseUri = Uri.parse(BASE_URL);
        Uri.Builder uriBuilder = baseUri.buildUpon();
        uriBuilder.appendPath("movie");
        uriBuilder.appendPath("popular");
        uriBuilder.appendQueryParameter("api_key", QueryUtils.API_KEY);
        uriBuilder.appendQueryParameter("page", Integer.valueOf(1).toString());

        Log.v(LOG_TAG, "onCreateLoader@URL built: " + uriBuilder.toString());

        return new ShowLoader(getActivity(), uriBuilder.toString());
    }


    @Override
    public void onLoadFinished(Loader<List<Show>> loader, List<Show> shows) {
        // Clear the adapter of previous earthquake data
        clearAdapter();

        // If there is a valid list of Shows, then add them to the adapter's
        // data set. This will trigger the ListView to update.
        if (shows != null && !shows.isEmpty()) {
            mShowAdapter.addItemsToList(shows, false);
            mShowAdapter.notifyDataSetChanged();
        }

        pb.setVisibility(View.GONE);
    }

    @Override
    public void onLoaderReset(Loader<List<Show>> loader) {
        // Loader reset, so we can clear out our existing data.
        clearAdapter();
    }


    private void clearAdapter(){
        List<Show> empty = new ArrayList<>();
        mShowAdapter.addItemsToList(empty, false);
        mShowAdapter.notifyDataSetChanged();
    }

谢谢

【问题讨论】:

    标签: android android-recyclerview searchview android-search


    【解决方案1】:

    您可以使用两个列表,一个包含所有元素(原始),一个包含查询的元素(这个应该使用 recyclerview 适配器)。查询时,只需从原始列表中选择并将它们添加到适配器列表中,然后通知更改。在添加新条目之前不要忘记清除适配器列表。

    编辑:您可以在onQueryTextChange 方法上尝试类似的方法。适应你自己的愿望。

    if(s != null && !s.isEmpty()) {
       for(String movie : originalList) {
          if(movie.toLowerCase().contains(s.toLowerCase()){
             adapter.add(movie);
          }
          notifyChanges();
        }
      }           
    } else { adapter.addAll(originalList); }
    

    【讨论】:

    • 那我怎么知道用户何时不再搜索?
    • 然后你可以使用addAll()方法将原始列表中的所有项目添加到适配器列表中,然后通知更改。
    • 您有两个列表。我们称它们为 res1 和 res2。 res1 包含所有电影, res2 为空。当用户进行搜索时,在 res1 中查找所有匹配的条目,将它们添加到 res2 并将 res2 提供给适配器。当用户进行另一次搜索时,再次查找 res1 中的每个匹配条目,将其添加到 res2 并将 res2 提供给适配器。当用户停止搜索时,添加从 res1 到 res2 (res2.addAll(res1)) 的所有内容,然后再次将 res2 提供给适配器。
    • 是的,我正在使用它,但我仍然无法让它工作。我检查信件的方式是否正确?即使在实施了两个列表之后,项目也没有任何变化。 E:实际上它可以正确地去除广告元素,但仍然有一些海报完全没有共同点
    • 现在我在 for(Show movie : searchList) 线上遇到了 ConcurrentModificationException
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    相关资源
    最近更新 更多