Search code examples
androidanimationandroid-recyclerviewsearchviewnotify

Call notifyItemRangechanged when text in searchbar is written Recyclerview android


I would like to add an animation on my RecyclerView every time the user types something in the SearchBar. I already have implemented a Filter method to filter the items, but fail to call notifyItemrangechanged in OnQuerytextChanged, so the appears. I have already tried something like this:

@Override
                public boolean onQueryTextChange(String newText) {


                    istyping = true;

                    ArrayList<String> templist = new ArrayList<>();

                    mSearchQuery = newText;

 //this line -->   adapter.notifyItemRangeChanged(0, namelistwithnumber.size());    <---



                    for (String temp : namelistwithnumber) {
                        if (temp.toLowerCase().contains(newText.toLowerCase())) {
                            templist.add(temp);
                        }
                    }

                    if (newText.isEmpty()){
                        mainlist.setAdapter(null);
                        adapter = new MyRecyclerViewAdapter(MainActivity.this, namelist);
                        mainlist.setAdapter(adapter);
                        adapter.notifyDataSetChanged();
                        istyping = false;
                    }

                    if (templist.size() == 0) {
                        mainlist.setAdapter(null);
                        noresults.setVisibility(View.VISIBLE);
                    } else {
                        if (!newText.isEmpty()){
                          adapter = new MyRecyclerViewAdapter(MainActivity.this, templist);
                            mainlist.setAdapter(adapter);
                            noresults.setVisibility(View.INVISIBLE);
                            adapter.setClickListener(MainActivity.this);

                        }
                        noresults.setVisibility(View.INVISIBLE);
                    }

                    return true;
                }

This is what I want to achieve:

animation

Any help is appreciated!!


Solution

  • Sina's answer seems good, it has good practices(except redundant dataBinding), but since you did not accept it, i assume you don't want to rewrite your code with those additional concepts. So here is simple solution:

    • Set setHasStableIds(true) to adapter
    • Override getItemId(int position) inside adapter
    • Add DefaultItemAnimator() to RecyclerView

    Step by step guide:

    1. Add default itemAnimator to your RecyclerView

    mainlist.setItemAnimator(new DefaultItemAnimator());
    

    2. Add function to adapter for updating list

    You should not reinitialize your MyRecyclerViewAdapter every time you change List of items. Remove list from constructor! Instead declare member varialbe List<NameListwithNumber> nameListWithNumber = new ArrayList<>(); inside your dapter class and add a function to your adapter:

    public void setItems(List<NameListwithNumber> newItems){
    nameListWithNumber.clear();
    nameListWithNumber.addAll(newItems);
    notifydatasetChanged();
    }
    

    3. Initialize adapter and set setHasStableIds(true)

    In your Activity declare your adapter as a global variable

    private MyRecyclerViewAdapter  myAdapter;
    

    (i'm not sure why would you need activity instance inside adapter tho)

    and initialize it inside onCreate() method

     myAdapter = new MyRecyclerViewAdapter(MainActivity.this);
     myAdapter.setHasStableIds(true);
     mainList.setAdapter(myAdapter);
    

    4. Override getItemId(int position) inside adapter

    inside your adapter add this function:

    @Override
    public long getItemId(int position) {
       return nameListWithNumber.get(position).id;
    }
    

    if your model does not have unique id just use return nameListWithNumber.get(position).hashCode();


    Finally Inside your public boolean onQueryTextChange(String newText) you need to change

      if (newText.isEmpty()) {
           adapter.setItems(nameList)
           istyping = false;
        }
      else {
        adapter.setItems(tempList)
        noresults.setVisibility(templist.size() == 0 ? View.VISIBLE : View.INVISIBLE)
    }
    

    Heres is the result of the exact same approach with just filtering done differently.

    enter image description here