Панель инструментов с временной фильтрацией SearchView RecyclerView

Мне нужно реализовать функцию поиска внутри моего приложения для Android, которое использует панель инструментов, SlidingTabLayout и ViewPager, которая содержит фрагменты. Внутри каждого фрагмента есть RecyclerView со списком элементов.

Данные RecyclerView статичны в отдельном классе (DataAccess.java), и эти списки обновляются, а RecyclerView обновляется только путем вызова (без передачи новых данных).

mRecyclerView.getAdapter().notifyDataSetChanged();

Есть ли простой способ временного фильтра RecyclerView без изменения данных и после того, как пользователь нажимает кнопку возврата на панели инструментов, чтобы удалить фильтр и показать список в списке.

Перед тем, как нажать значок поиска внутри меню панели инструментов:

enter image description here

Итак, когда пользователь вводит "Josip...", фильтр будет активным

enter image description here

и после нажатия кнопки X в SearchView пользователь получит те же данные, что и раньше, без фильтра.

@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

Я хотел добавить комментарий, но из-за меньшей репутации... Я отвечаю на пост. Этот метод отлично работает, если (item.toLowerCase(). Содержит (queryText)), но что делать, если совпадение не найдено в первой итерации. Затем он будет входить иначе, не зацикливаясь в списке 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");
    }

Ответ 3

Я не возражаю против данного и принятого ответа. Есть место для возможных ошибок производительности. Нужно использовать интерфейс Filterabe. Внедрение этого будет вести себя как ol'good ListView, который сделал асинхронную фильтрацию. Тогда вам нужно написать свой собственный Filter и создать экземпляр в переопределенном методе getFilter();

В моем случае я использовал Filter для сортировки адаптера многих (да, многих) элементов. Это был junky, сортирующий его на 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());
    }

}