Android: how do I maintain the View for CardViews in a RecyclerView list?

青春壹個敷衍的年華 提交于 2019-12-24 07:59:25

问题


I have a RecyclerView list that shows a vertical list of CardViews. The AppBar has an action_search MenuItem that handles a SearchView method when clicked on. The SearchView runs a filter method that allows the CardView data to be searched.

I set up a filterList to hold filtered CardViews from the search results. The filter() method clears the filterList before conducting the search query. The problem is that the filterList.clear() destroys the View of the existing RecyclerView CardViews and the UI reverts to the blank RecyclerView layout.

If I back button out of the app and then re-start the app, the RecyclerView loads the CardViews correctly and when I click on the Search MenuItem I am then able to search correctly; that is the View dynamically and correctly updates to only show those CardViews that match the Search text querty. What am I missing here?

MainActivity.java

public class MainActivity extends AppCompatActivity implements
    RecyclerItemClickListener {

    private MyRecylerAdapter adapter;
    ...
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.cardview_menu, menu);
        MenuItem item = menu.findItem(R.id.action_search);
        SearchView searchView = (SearchView) MenuItemCompat.getActionView item);            
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                adapter.filter(query);
                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                adapter.filter(newText);
                return true;
            }
        });
        return;
}

 Adapter.java

 public class MyRecylerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

     private List<ListItem> listItems, filterList;
     private Context mContext;

     public MyRecylerAdapter(Context context, List<ListItem> listItems) {
         this.listItems = listItems;
         this.mContext = context;
         this.filterList = new ArrayList<>();
         // Copy the original list to the filter list to be used for setting row
         // values when returning search data items.
         this.filterList.addAll(this.listItems);
     }

     public void clear() {
         while (getItemCount() > 0) {
             remove(getItem(0));
         }
     }

     public void filter(final String text) {

     new Thread(new Runnable() {
         @Override
         public void run() {

            filterList.clear();

            if(TextUtils.isEmpty(text)) {
                filterList.addAll(listItems);
            } else {                    
                for (ListItem item : listItems) {
                    if (item.getTodo().toLowerCase().contains(text.toLowerCase())) {                        
                        filterList.add(item);
                    }
                }
            }

            // Set on UI Thread
            ((Activity) mContext).runOnUiThread(new Runnable() {
                @Override
                public void run() {                        
                    notifyDataSetChanged();
                }
            });
        }
    }).start();
} 

}


回答1:


try this code.. set this method in adapter

public void setFilter(ArrayList<ListItem> listItem) {
        listItems = new ArrayList<>();
        listItems.addAll(listItem);
        notifyDataSetChanged();
    }

and use like this in onQueryTextChange()

final ArrayList<ListItem> filteredModelList = filter(listItems, newText);
adapter.setFilter(filteredModelList);

and this is the filter method.

private ArrayList<ListItem> filter(ArrayList<ListItem> models, String query) {
        query = query.toLowerCase();

        final ArrayList<ListItem> filteredModelList = new ArrayList<>();
        for (ListItem model : models) {
            final String text = model.getTodo().toLowerCase();
            if (text.contains(query)) {
                filteredModelList.add(model);
            }
        }

        return filteredModelList;
    }

and remove last two lines from your adapter constructor. with this code you dont have to create second array list object for filter, so you dont need to clear your arraylist object.. it works good when you write or clear text in searchview.



来源:https://stackoverflow.com/questions/41969397/android-how-do-i-maintain-the-view-for-cardviews-in-a-recyclerview-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!