Android Filter Recyclerview by using SearchView in ToolBar or actionbar
In this tutorial, we will learn how can we filter the recyclerview item by using the Search view in toolbar or action bar? Recyclerview is the major used component in building the android application. And if the data is very huge then we can not find the specific item by scroll. So we need to filter by name while entering the text on search view. SearchView is an awesome component that provides the search with animated expand and collapse action.
Here is the recommended video which I have implemented search view in this app. Please check this video for better understanding.
Let’s integrate this feature in the sample project. Very first thing we need to add relevant dependencies in your build.gradle file.
compile 'com.android.support:recyclerview-v7:26.0.1' compile 'com.android.support:cardview-v7:26.0.1' compile 'com.android.support:design:26.0.1'
Now I need to create the menu_main.xml of item search inside the res/menu folder.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_search"
android:title="@string/app_name"
app:actionViewClass="android.support.v7.widget.SearchView"
android:icon="@android:drawable/ic_menu_search"
app:showAsAction="always|collapseActionView"
/>
</menu>
Let’s load the data on recyclerview from a database. I am not going into the deep to load the data from the database. here I suppose that I have fetched the data of the table and loaded into List. As everyone knows that we need to bind the recyclerview item by an adapter. Let’s create the adapter and resource layout to inflate the data on view.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
app:cardCornerRadius="0dp"
android:layout_margin="3dp"
app:cardUseCompatPadding="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:padding="8dp"
android:id="@+id/relative"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/movie_icon"
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="200dp" />
<RelativeLayout
android:id="@+id/info"
android:padding="5dp"
android:layout_below="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/name"
android:textSize="15sp"
android:textStyle="bold"
android:text="@string/app_name"
android:ellipsize="end"
android:singleLine="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:textSize="13sp"
android:id="@+id/releasyear"
android:text="@string/app_name"
android:layout_below="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_below="@+id/releasyear"
android:id="@+id/star"
android:src="@drawable/ic_stars_yellow_900_24dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/rating"
android:layout_below="@+id/releasyear"
android:layout_toRightOf="@+id/star"
android:layout_centerVertical="true"
android:layout_marginTop="3dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
Let’s use this layout for my adapter.
public class ImDbAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<IMBD> itemModels;
private Context context;
private onItemClickListener listener;
public ImDbAdapter(Context context, List<IMBD> imbdList, Fragment fragment) {
this.itemModels = imbdList;
this.context = context;
this.listener = (onItemClickListener) fragment;
}
@Override
public int getItemCount() {
return itemModels.size();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_layout, viewGroup, false);
return new ItemViewHolder(itemView);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
IMBD model = itemModels.get(position);
initializeViews(model, holder, position);
}
private void initializeViews(final IMBD model, final RecyclerView.ViewHolder holder, final int position) {
((ItemViewHolder)holder).name.setText(model.getName());
((ItemViewHolder)holder).releasyear.setText("Release Year: "+model.getYearofrelease());
((ItemViewHolder)holder).rating.setText(""+model.getRating());
((ItemViewHolder)holder).relative.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.itemDetailClick(model);
}
});
String imageUrl = model.getImageurl();
if (imageUrl != null && !imageUrl.isEmpty()){
Picasso.with(context)
.load(imageUrl)
.placeholder(R.drawable.movie_icon)
.error(R.drawable.movie_icon)
.into(((ItemViewHolder)holder).imageView);
}
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.name)
TextView name;
@BindView(R.id.releasyear)
TextView releasyear;
@BindView(R.id.rating)
TextView rating;
@BindView(R.id.imageView)
ImageView imageView;
@BindView(R.id.relative)
RelativeLayout relative;
public ItemViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
public interface onItemClickListener{
public void itemDetailClick(IMBD imbd);
}
public void setSearchResult(List<IMBD> result) {
itemModels = result;
notifyDataSetChanged();
}
}
Here I am using the fragment So we need to enable the menu option in onCreate() of Fragment and override the onCreateOptionMenu() to allow searches to filter the recycled view data by using SearchView.
I used MVP design pattern with Dagger2 dependency injection in this sample project. If you want to get the detail of MVP design pattern in Java then Please check this post MVP architectural design pattern with RxJava. Here is the detail about the Dagger2 Dependency Injection.
public class ImdbListFragment extends Fragment implements ImdbListContract.View, ImDbAdapter.onItemClickListener, SearchView.OnQueryTextListener{
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@Inject
ImdbListContract.Presenter mPresenter;
private ImDbAdapter mImDbAdapter;
private List<IMBD> mListImDb;
public static ImdbListFragment newInstance() {
return new ImdbListFragment();
}
@Override
public void onResume() {
super.onResume();
mPresenter.subscribe();
}
@Override
public void onPause() {
super.onPause();
mPresenter.unSubscribe();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// do things if you want to create only first time when activity created.
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
injectDependency();
mPresenter.attachView(this);
setHasOptionsMenu(true);
}
private void injectDependency() {
ApplicationComponent applicationComponent = ((MainApplication) getActivity().getApplication()).getApplicationComponent();
ImdbListComponent imdbListComponent = DaggerImdbListComponent.builder()
.applicationComponent(applicationComponent)
.imdbListModule(new ImdbListModule())
.build();
imdbListComponent.inject(this);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_imdb_list, container, false);
ButterKnife.bind(this, root);
if (mPresenter != null) {
if (mPresenter.getCountDb() > 0) {
mPresenter.loadImDbDb();
} else {
Log.v("", "Error in loading.");
}
}
return root;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.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);
item.setOnActionExpandListener( new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// Do something when collapsed
mImDbAdapter.setSearchResult(mListImDb);
return true; // Return true to collapse action view
}
});
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
final List<IMBD> filteredModelList = filter(mListImDb, newText);
mImDbAdapter.setSearchResult(filteredModelList);
return true;
}
private List<IMBD> filter(List<IMBD> models, String query) {
query = query.toLowerCase();
final List<IMBD> filteredModelList = new ArrayList<>();
for (IMBD model : models) {
final String text = model.getName().toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
@Override
public void onImDbOk(List<IMBD> imbdList) {
mListImDb = imbdList;
mImDbAdapter = new ImDbAdapter(getActivity(), imbdList, this);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
recyclerView.setAdapter(mImDbAdapter);
}
@Override
public void showLoadErrorMessage(String errorMsg) {
Toast.makeText(getActivity(), errorMsg, Toast.LENGTH_LONG).show();
}
@Override
public void showEmptyView(boolean isShow) {
// show error view if any
}
@Override
public void itemDetailClick(IMBD imbd) {
String imbdDetailLink = imbd.getDetailLink();
}
}

Wrapping Up: This is the great implementation of RecylerView item filter by using the SearchView in ToolBar. Let’s use this feature in your app to make your application more awesome and powerful.
Here is the Github link for full source code.
Please do subscribe your email to get the every newsletter from this blog and if you feel that this post helps you then do not forget to share and comment below.
You can learn all articles of MobologicPlus from the android app, which is available to download below.
[appbox googleplay mobi.androapp.mobologicplus.c7929]
Happy Coding 🙂
I am a very enthusiastic Android developer to build solid Android apps. I have a keen interest in developing for Android and have published apps to the Google Play Store. I always open to learning new technologies. For any help drop us a line anytime at contact@mobologicplus.com

Great tutorial sunil… Can you please guide on how to filter search view if there are two or more lists all placed in different activities….
thank you sir
Thank you for sharing such good information.