Monday, 2 May 2016

Simple RecyclerView example with filter option in Android

Hi Guys, Maybe you all are expert in terms of using RecyclerView in android. This blog is simple example for using filter option with RecyclerView adapter.



As for now you will instantiate RecyclerView and set the adapter to RecyclerView as following way.
RecyclerView list = (RecyclerView) findViewById(R.id.list);
list.setLayoutManager(new LinearLayoutManager(this));
list.setHasFixedSize(true);
ArrayList<Number> numbers = new ArrayList<>();
String ONEs[] = {"ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN"};
String TENs[] = {"ZERO", "TEN", "TWENTY", "THIRTY", "FOURTY", "FIFTY", "SIXTY",  "SEVENTY", "EIGHTY", "NINETY", "HUNDRED"};
String HUNDREDS[] = {"ZERO", "HUNDRED", "TWO HUNDRED", "THREE HUNDRED", "FOUR HUNDRED", "FIVE HUNDRED", "SIX HUNDRED", "SEVEN HUNDRED", "EIGHT HUNDRED", "NINE HUNDRED", "THOUSAND"};
for (int i = 0; i <= 10; i++) {
    Number number = new Number();
    number.setONEs(i+"");
    number.setTENs(i * 10+"");
    number.setHUNDREDs(i * 100+"");
    number.setTextONEs(ONEs[i]);
    number.setTextTENs(TENs[i]);
    number.setTextHUNDREDs(HUNDREDS[i]);
    this.numbers.add(number);
}
adapter = new NumbersAdapter(this.numbers);
list.setAdapter(adapter);
And also you will create your options menu and inflate SearchView as following way.
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        final MenuItem item = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item);
        searchView.setOnQueryTextListener(this);
        return true;
    }
So by above code your activity/fragment will implement SearchView.OnQueryTextListener. So you will have onQueryTextChange method from this listener. Just change this method like following to start filtering with this adapter.
    @Override
    public boolean onQueryTextChange(String newText) {
        final List<Number> filteredModelList = filter(numbers, newText);
        Log.v("App", newText + ", " + numbers.size() + ", " + filteredModelList.size());
        adapter.animateTo(filteredModelList);
        list.scrollToPosition(0);
        return true;
    }
The filter method from above code will return the filtered list as following.
    private List<Number> filter(List<Number> numbers, String query) {
        query = query.toLowerCase();

        ArrayList<Number> filteredCompanyList = new ArrayList<>();
        for (Number client : numbers) {
            final String textOne = client.getTextONEs().toLowerCase();
            final String textTen = client.getTextTENs().toLowerCase();
            final String textHundred = client.getTextHUNDREDs().toLowerCase();
            final String TENs = client.getTENs();
            final String ONEs = client.getONEs();
            final String HUNDREDs = client.getHUNDREDs();
            if (textOne.contains(query) || TENs.contains(query) || ONEs.contains(query) || HUNDREDs.contains(query) || textTen.contains(query) || textHundred.contains(query)) {
                filteredCompanyList.add(client);
            }
        }
        return filteredCompanyList;
    }
And your adapter will have the following related methods to perform this filter with animation.
    public void animateTo(List<Number> models) {
        applyAndAnimateRemovals(models);
        applyAndAnimateAdditions(models);
        applyAndAnimateMovedItems(models);
    }

    private void applyAndAnimateRemovals(List<Number> newModels) {
        for (int i = numbers.size() - 1; i >= 0; i--) {
            final Number model = numbers.get(i);
            if (!newModels.contains(model)) {
                removeItem(i);
            }
        }
    }

    private void applyAndAnimateAdditions(List<Number> newModels) {
        for (int i = 0, count = newModels.size(); i < count; i++) {
            final Number model = newModels.get(i);
            if (!numbers.contains(model)) {
                addItem(i, model);
            }
        }
    }

    private void applyAndAnimateMovedItems(List<Number> newModels) {
        for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) {
            final Number model = newModels.get(toPosition);
            final int fromPosition = numbers.indexOf(model);
            if (fromPosition >= 0 && fromPosition != toPosition) {
                moveItem(fromPosition, toPosition);
            }
        }
    }

    public Number removeItem(int position) {
        final Number model = numbers.remove(position);
        notifyItemRemoved(position);
        return model;
    }

    public void addItem(int position, Number model) {
        numbers.add(position, model);
        notifyItemInserted(position);
    }

    public void moveItem(int fromPosition, int toPosition) {
        final Number model = numbers.remove(fromPosition);
        numbers.add(toPosition, model);
        notifyItemMoved(fromPosition, toPosition);
    }


I hope this post is useful to you. kindly share your feedback as comment here.


Simple RecyclerView example in Android

Simple recyclerview example with checkbox in Android

Dynamically change ListView to GridView and Vice Versa using RecyclerView

Source code on GitHub



Thank You