Android - Implementing search filter to a RecyclerView Android - Implementing search filter to a RecyclerView android android

Android - Implementing search filter to a RecyclerView


in your adapter add new function for update the list

public void updateList(List<DataHolder> list){     displayedList = list;     notifyDataSetChanged();}

add textWatcher for search lets say you are using Edittext as search field

searchField.addTextChangedListener(new TextWatcher() {        @Override        public void onTextChanged(CharSequence s, int start, int before, int count) {            // TODO Auto-generated method stub        }        @Override        public void beforeTextChanged(CharSequence s, int start, int count, int after) {            // TODO Auto-generated method stub        }        @Override        public void afterTextChanged(Editable s) {            // filter your list from your input            filter(s.toString());            //you can use runnable postDelayed like 500 ms to delay search text        }    });

Simple filter function

void filter(String text){     List<DataHolder> temp = new ArrayList();     for(DataHolder d: displayedList){           //or use .equal(text) with you want equal match           //use .toLowerCase() for better matches           if(d.getEnglish().contains(text)){               temp.add(d);           }     }     //update recyclerview     disp_adapter.updateList(temp);}


With Butterknife

@OnTextChanged(R.id.feature_manager_search)protected void onTextChanged(CharSequence text) {    filter(text.toString());}


i have done like this

.XMl file

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><android.support.design.widget.AppBarLayout    android:id="@+id/appBar"    android:layout_width="match_parent"    android:layout_height="wrap_content"    app:elevation="1dp"    android:theme="@style/AppTheme.AppBarOverlay"    android:layout_marginBottom="@dimen/bottom_margin">    <android.support.v7.widget.Toolbar        android:id="@+id/toolbar"        android:layout_width="match_parent"        android:layout_height="?attr/actionBarSize"        app:popupTheme="@style/AppTheme.PopupOverlay"/></android.support.design.widget.AppBarLayout><EditText    android:id="@+id/etSearch"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:hint="Search"    android:imeOptions="actionDone"    android:singleLine="true"/><android.support.v7.widget.RecyclerView    android:id="@+id/rvCategory"    android:layout_width="match_parent"    android:layout_height="match_parent"></android.support.v7.widget.RecyclerView></LinearLayout>

.JAVA Class file

package com.example.myapplication;import android.content.Context;import android.content.Intent;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.CardView;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.support.v7.widget.Toolbar;import android.text.Editable;import android.text.TextWatcher;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.EditText;import android.widget.Filter;import android.widget.Filterable;import android.widget.ImageView;import android.widget.TextView;import org.json.JSONObject;import java.util.ArrayList;public class Home extends AppCompatActivity implements ResultCallBack{SQLiteDatabase db;ArrayList<String> alCategorName=new ArrayList<>();RecyclerView rvCategory;EditText etSearch;Category bookadapter;ArrayList<String> alBookInfo;String strURL="http://localhost:21246/api/TreasuryBooks?BookId=1";@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_home);    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);    toolbar.setTitleTextColor(getResources().getColor(R.color.white));    setSupportActionBar(toolbar);//        AsyncTask_WebAPI asyncTask=new AsyncTask_WebAPI(this,strURL,this);//        asyncTask.execute();    etSearch=(EditText)findViewById(R.id.etSearch);    etSearch.setText("");    DatabaseAccess da= DatabaseAccess.getInstance(this);    db=da.open();    alBookInfo=new ArrayList<String>();    Cursor c = db.rawQuery("select BookName from Books", null);    int rows = c.getCount();    c.moveToFirst();    for(int i=0;i<rows;i++)    {        String strBoookName=c.getString(c.getColumnIndex("BookName"));        alBookInfo.add(strBoookName);        c.moveToNext();    }    c.close();    db.close();    rvCategory=(RecyclerView)findViewById(R.id.rvCategory);    //Recycler view adapter    bookadapter=new Category(this,alBookInfo);    rvCategory.setLayoutManager(new LinearLayoutManager(this));    rvCategory.setAdapter(bookadapter);    //text change listner    etSearch.addTextChangedListener(new TextWatcher() {        @Override        public void beforeTextChanged(CharSequence s, int start, int count,             int after) {        }        @Override        public void onTextChanged(CharSequence s, int start, int before, int count) {           bookadapter.getFilter().filter(s.toString());        }        @Override        public void afterTextChanged(Editable s) {        }    });}@Overridepublic void onBackPressed() {    Home.this.finish();}@Overrideprotected void onRestart() {    super.onRestart();    etSearch.setText("");}@Overridepublic void onResultListener(Object object) {    JSONObject jsonObject=(JSONObject)object;    try {        String strId = jsonObject.getString("id");        String strBookId=jsonObject.getString("BookId");        String strBookName=jsonObject.getString("BookName");        db.rawQuery("insert into Books values('"+strId+"','"+strBookId+"','"+strBookName+"'",null);    }    catch (Exception e)    {        e.printStackTrace();    }}

Recyclerview adapter

  //Recycler view adapter Class with filterable interface   private class Category extends RecyclerView.Adapter<viewHolder> implements Filterable{    ArrayList<String> alBooks=new ArrayList<String>();    Context context;    viewHolder holder;    public  Category()    {}    public Category(Context context,ArrayList<String> albooks)    {        this.context=context;        this.alBooks=albooks;    }    @Override    public int getItemCount() {        return alBooks.size();    }    @Override    public viewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View v=    LayoutInflater.from(parent.getContext()).inflate(R.layout.home_cardview,parent,false);        holder=new viewHolder(v);        return holder;    }    @Override    public void onBindViewHolder(viewHolder holder, int position) {        holder.tvBookName.setText(alBooks.get(position));    }    private Filter fRecords;   //return the filter class object    @Override    public Filter getFilter() {        if(fRecords == null) {            fRecords=new RecordFilter();        }        return fRecords;    }   //filter class    private class RecordFilter extends Filter {        @Override        protected FilterResults performFiltering(CharSequence constraint) {            FilterResults results = new FilterResults();            //Implement filter logic    // if edittext is null return the actual list            if (constraint == null || constraint.length() == 0) {                //No need for filter                results.values = alBookInfo;                results.count = alBookInfo.size();            } else {               //Need Filter        // it matches the text  entered in the edittext and set the data in adapter list                ArrayList<String> fRecords = new ArrayList<String>();                for (String s : alBookInfo) {                    if (s.toUpperCase().trim().contains(constraint.toString().toUpperCase().trim())) {                        fRecords.add(s);                    }                }                results.values = fRecords;                results.count = fRecords.size();            }            return results;        }        @Override        protected void publishResults(CharSequence constraint,FilterResults results) {       //it set the data from filter to adapter list and refresh the recyclerview adapter            alBooks = (ArrayList<String>) results.values;            notifyDataSetChanged();           }       }   }   private class viewHolder extends  RecyclerView.ViewHolder {    CardView cv;    TextView tvBookName;    viewHolder(final View itemview) {        super(itemview);        cv = (CardView) itemview.findViewById(R.id.cardview);        tvBookName = (TextView) itemview.findViewById(R.id.categoryName);        itemview.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new       Intent(Home.this,Act_Fragment_Container.class);                intent.putExtra("BookName", tvBookName.getText());                startActivity(intent);            }        });    }   }

}

add recycler view adapter in same class to avoid confusion....


Implement SearchView.OnQueryTextListener

public class Countries_List extends AppCompatActivity  implements SearchView.OnQueryTextListener {    //your Model Class    List<Countries> dataList, filteredDataList;    @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.menu_main, menu);        MenuItem item=menu.findItem(R.id.action_search);        SearchView searchView=(SearchView)MenuItemCompat.getActionView(item);        searchView.setOnQueryTextListener(this);        return true;    }    @Override    public boolean onQueryTextSubmit(String query) {        return false;    }    @Override    public boolean onQueryTextChange(String newText) {        filteredDataList = filter(dataList, newText);        mAdapter.setFilter(filteredDataList);        return true;    }    public boolean onOptionsItemSelected(MenuItem item) {        // Handle action bar item clicks here. The action bar will        // automatically handle clicks on the Home/Up button, so long        // as you specify a parent activity in AndroidManifest.xml.        int id = item.getItemId();        //noinspection SimplifiableIfStatement        if (id == R.id.action_search) {            return true;        }        return super.onOptionsItemSelected(item);    }    private List<Countries> filter(List<Countries> dataList, String newText) {        newText=newText.toLowerCase();        String text;        filteredDataList=new ArrayList<>();        for(Countries dataFromDataList:dataList){            text=dataFromDataList.getTitle().toLowerCase();            if(text.contains(newText)){                filteredDataList.add(dataFromDataList);            }        }        return filteredDataList;    }}

And, in your Adapter Class:

void setFilter(List<Countries> FilteredDataList) {        countriesList = FilteredDataList;        notifyDataSetChanged();    }