Toolbar with SearchView temporary filtering RecyclerView

落爺英雄遲暮 提交于 2019-11-28 19:22:08

问题


I need to implement search functionality inside my android app which uses toolbar, SlidingTabLayout and ViewPager that holds fragments. Inside each fragment there is a RecyclerView with list of items.

RecyclerView data is static defined in separate class (DataAccess.java) and those lists are updated and RecyclerView gets refreshed just by calling (without passing new data)

mRecyclerView.getAdapter().notifyDataSetChanged();

Is there any simple way to temporary filter RecyclerView without changing the data and after the user presses return button inside Toolbar to remove the filter and show inital list.

Before pressing Search icon inside toolbar menu:

So when the user is typing "Josip..." the filter will be active

and after he presses the X button in SearchView the user will get the same data as before without filter.

@Override 
public boolean onQueryTextChange(String newText) {
    // filter data (temporary remove all items from DataAccess.list that don't .startsWith(newText)
}

@Override 
public boolean onQueryTextSubmit(String query)
    // Doesn't help if I revert deleted items here
}

回答1:


@Override 
public boolean onQueryTextSubmit(String query){
    ((ItemAdapter) myRecList.getAdapter()).setFilter(query)
}

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

    private List<String> visibleObjects;
    private List<String> allObjects;

    .....

    public void flushFilter(){
        visibleObjects=new ArrayList<>();
        visibleObjects.addAll(allObjects);
        notifyDataSetChanged();
    }

    public void setFilter(String queryText) {

        visibleObjects = new ArrayList<>();
        constraint = constraint.toString().toLowerCase();
        for (String item: allObjects) {            
                if (item.toLowerCase().contains(queryText))                     
                    visibleObjects.add(item);            
        }
       notifyDataSetChanged();
    }
}



回答2:


I wanted to add as comment but due to less reputation...I am answering post. This method works fine if (item.toLowerCase().contains(queryText)) but what to do if match is not found in first iteration.then it will go in else part without looping throughout allObjects list...

for (RouteByATMList.Route_ATM item: Main_ATMItemList)
        {

            if (item.ATMNumber.contains(queryText)) {
                visibleObjects.add(item);
            }else {
                Toast.makeText(mContext,"No search result found!",Toast.LENGTH_SHORT).show();
                break;
            }
        }

I got the answer from my superior ,hope it helps.

public void setFilter(String queryText) {
        visibleObjects = new ArrayList<>();
        for (RouteByATMList.Route_ATM item: Main_ATMItemList)
        {
            if (item.ATMNumber.contains(queryText))
            {
                visibleObjects.add(item);
            }
        }

        if(visibleObjects.size()==0){
            Toast.makeText(mContext,"No search result found!",Toast.LENGTH_SHORT).show();
        }

        notifyDataSetChanged();
        Log.e("dataset changed","dataset changed");
    }



回答3:


I don't oppose the given and accepted answer. There is a room for possible performance pitfalls. One should make use of Filterabe interface. Having this implemented will behave as ol'good ListView that did the filtering asynchronously. Then all you need is to write your own Filter and instantiate it in the overridden getFilter() method;

In my case I used Filter to sort an adapter of many (yeah, many many) items. It was junky sorting it on UI-thread.

So I had this abstract class

public abstract class BaseFilterableRecyclerViewAdapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> implements Filterable {

    private Context mContext;
    public BaseFilterableRecyclerViewAdapter(Context context) {
        this.mContext = context;
    }
    public abstract void sort(SortingFilter.Sort sortingStrategy);

    //...Other methods

}

And the class that inherit:

public class ItemAdapter extends BaseFilterableRecyclerViewAdapter<RecyclerView.ViewHolder>{


  //... RecyclerView methods


  @Override
    public Filter getFilter() {
        return new SortingFilter(mData) {
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if (results.values != null) {
                    int last = mData.size();
                    mData = (List<Product>) results.values;
                    notifyDataSetChanged();
                }
            }
        };
    }



    @Override
    public void sort(SortingFilter.Sort sortingStrategy) {
        getFilter().filter(sortingStrategy.toString());
    }

}


来源:https://stackoverflow.com/questions/27787246/toolbar-with-searchview-temporary-filtering-recyclerview

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