带有 SearchView 临时过滤 RecyclerView 的工具栏
Toolbar with SearchView temporary filtering RecyclerView
我需要在我的 android 应用程序中实现搜索功能,该应用程序使用工具栏、SlidingTabLayout 和包含片段的 ViewPager。在每个片段中都有一个带有项目列表的 RecyclerView。
RecyclerView 数据是在单独的 class (DataAccess.java) 中静态定义的,这些列表会更新,RecyclerView 只需调用即可刷新(不传递新数据)
mRecyclerView.getAdapter().notifyDataSetChanged();
是否有任何简单的方法可以在不更改数据的情况下临时过滤 RecyclerView,并且在用户按下工具栏内的 return 按钮以删除过滤器并显示初始列表后。
在工具栏菜单中按下搜索图标之前:
所以当用户输入时 "Josip..." 过滤器将被激活
在他按下 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
}
@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();
}
}
我想添加为评论,但由于声誉较低...我正在回答 post。
如果 (item.toLowerCase().contains(queryText)) 此方法工作正常但是如果在第一个 iteration.then 中找不到匹配项怎么办它将进入 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");
}
我不反对给出并接受的答案。存在可能的性能缺陷的空间。应该使用 Filterabe
界面。实现此功能将表现得像 ol'good ListView
那样异步进行过滤。那么你所需要的就是编写自己的 Filter
并在重写的 getFilter()
方法中实例化它;
在我的例子中,我使用 Filter
对许多(是的,很多很多)项目的适配器进行排序。在 UI-thread 上对它进行排序很垃圾。
所以我有了这个摘要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
}
以及继承的class:
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());
}
}
我需要在我的 android 应用程序中实现搜索功能,该应用程序使用工具栏、SlidingTabLayout 和包含片段的 ViewPager。在每个片段中都有一个带有项目列表的 RecyclerView。
RecyclerView 数据是在单独的 class (DataAccess.java) 中静态定义的,这些列表会更新,RecyclerView 只需调用即可刷新(不传递新数据)
mRecyclerView.getAdapter().notifyDataSetChanged();
是否有任何简单的方法可以在不更改数据的情况下临时过滤 RecyclerView,并且在用户按下工具栏内的 return 按钮以删除过滤器并显示初始列表后。
在工具栏菜单中按下搜索图标之前:
所以当用户输入时 "Josip..." 过滤器将被激活
在他按下 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
}
@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();
}
}
我想添加为评论,但由于声誉较低...我正在回答 post。 如果 (item.toLowerCase().contains(queryText)) 此方法工作正常但是如果在第一个 iteration.then 中找不到匹配项怎么办它将进入 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");
}
我不反对给出并接受的答案。存在可能的性能缺陷的空间。应该使用 Filterabe
界面。实现此功能将表现得像 ol'good ListView
那样异步进行过滤。那么你所需要的就是编写自己的 Filter
并在重写的 getFilter()
方法中实例化它;
在我的例子中,我使用 Filter
对许多(是的,很多很多)项目的适配器进行排序。在 UI-thread 上对它进行排序很垃圾。
所以我有了这个摘要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
}
以及继承的class:
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());
}
}