使用SearchView临时过滤RecyclerView的工具栏

时间:2015-01-05 20:19:30

标签: android-fragments searchview android-recyclerview android-toolbar

我需要在我的Android应用程序中实现搜索功能,它使用工具栏,SlidingTabLayout和保存片段的ViewPager。在每个片段中都有一个带有项目列表的RecyclerView。

RecyclerView数据是在单独的类(DataAccess.java)中静态定义的,并且这些列表已更新,只需通过调用(不传递新数据)即可刷新RecyclerView

mRecyclerView.getAdapter().notifyDataSetChanged();

有没有简单的方法来临时过滤RecyclerView而不更改数据,并且在用户按下工具栏内的返回按钮后删除过滤器并显示初始列表。

在工具栏菜单中按“搜索”图标之前:

enter image description here

因此,当用户输入“Josip ...”时,过滤器将处于活动状态

enter image description here

在他按下SearchView中的X按钮后,用户将获得与之前相同的数据而不使用过滤器。

@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
}

3 个答案:

答案 0 :(得分:23)

@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();
    }
}

答案 1 :(得分:3)

我想添加评论,但由于声誉较低......我正在回复帖子。 如果(item.toLowerCase()。contains(queryText))此方法可以正常工作但是如果在第一次迭代中找不到匹配该怎么办。然后它将进入else部分而不遍及allObjects列表...

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;
            }
        }

我得到了我的上司的答案,希望它有所帮助。

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");
    }

答案 2 :(得分:3)

我不反对给出和接受的答案。存在可能存在性能缺陷的空间。一个人应该使用Filterabe接口。执行此操作将表现为ol'good ListView异步进行过滤。然后你只需要编写自己的Filter并在重写的getFilter()方法中实例化它;

在我的情况下,我使用Filter对许多(是的,很多)项目的适配器进行排序。它是在UI线程上排序的垃圾。

所以我有了这个抽象类

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

}

继承的课程:

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());
    }

}