In this post we will cover how to implement searchview filter with recyclerview.
How to add SeachView widget, We will add SearchView as an item to our options menu and make it expandable with the collapseActionView attribute
We will cover
Add SearchView widget
To add SearchView widget we will create menu item with passing Searchview widget as class name
<item android:id="@+id/action_search" android:icon="@android:drawable/ic_menu_search" android:title="Search" app:actionViewClass="androidx.appcompat.widget.SearchView" app:showAsAction="ifRoom|collapseActionView" /> |
Use SearchView inside activity
To use SearchiView we need to create searchview instance from menu item inside onCreateOptionsMenu()
override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.example_menu,menu) var searchItem=menu?.findItem(R.id.action_search) var searchView=searchItem?.actionView as SearchView; searchView.setImeOptions(EditorInfo.IME_ACTION_DONE) searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { return false } override fun onQueryTextChange(newText: String?): Boolean { return false } }) return true } |
Apply Search Filter inside Adapter
Implement adapter class with Filterable interface to handle search filter. This FIlterable has method getFilter() which will return the Filter() instance.
In the Filter class we will implement search filter logic.
Complete Example code for Recyclerview with SearchView Widget in Android Kotlin
Activity class
package com.rrtutors.androidtutorials import android.os.Bundle import android.view.Menu import android.view.inputmethod.EditorInfo import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SearchView import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.activity_recyclerview_search.* class RecyclerviewSearch : AppCompatActivity() { lateinit var listData:ArrayList<ExampleData>; lateinit var adapter:DataAdapter; override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_recyclerview_search) prepareData() init() } fun prepareData() { listData= ArrayList<ExampleData>(); listData.add(ExampleData("String1 1","String2 1",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 2","String2 2",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 3","String2 3",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 4","String2 4",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 5","String2 5",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 6","String2 6",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 7","String2 7",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 8","String2 8",R.mipmap.ic_launcher)) listData.add(ExampleData("String1 9","String2 9",R.mipmap.ic_launcher)) } fun init() { recyclerview.layoutManager=LinearLayoutManager(applicationContext) adapter=DataAdapter(listdata = listData); recyclerview.adapter=adapter } override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.example_menu,menu) var searchItem=menu?.findItem(R.id.action_search) var searchView=searchItem?.actionView as SearchView; searchView.setImeOptions(EditorInfo.IME_ACTION_DONE) searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { return false } override fun onQueryTextChange(newText: String?): Boolean { adapter.getFilter().filter(newText) return false } }) return true } } |
Adapter class
package com.rrtutors.androidtutorials import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Filter import android.widget.Filterable import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.layout_data_item.view.* class DataAdapter(var listdata:ArrayList<ExampleData>): RecyclerView.Adapter<DataAdapter.DataViewHolder>(), Filterable { lateinit var listdataSearch:ArrayList<ExampleData> init { listdataSearch= ArrayList() listdataSearch.addAll(listdata) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DataViewHolder { return DataViewHolder( LayoutInflater.from(parent.context).inflate(R.layout.layout_data_item, parent, false) ); } override fun getItemCount(): Int { return listdataSearch.size } override fun onBindViewHolder(holder: DataViewHolder, position: Int) { holder.image_view.setImageResource(listdataSearch.get(position).img) holder.text_view1.text=listdataSearch.get(position).str1; holder.text_view2.text=listdataSearch.get(position).str2; } class DataViewHolder( itemView: View): RecyclerView.ViewHolder(itemView) { var text_view1=itemView.text_view1; var text_view2=itemView.text_view2; var image_view=itemView.image_view; } //class SearchFilter(val listdata:ArrayList<ExampleData>): override fun getFilter(): Filter { return object : Filter() { override fun performFiltering(p0: CharSequence?): Filter.FilterResults { var listFilter=ArrayList<ExampleData>(); if(p0==null||p0.isEmpty()) { listFilter.addAll(listdata) }else { val filterPattern: String = p0.toString().toLowerCase().trim() for (item in listdata) { if (item.str1.toLowerCase().contains(filterPattern)) { listFilter.add(item) } } } val results = Filter.FilterResults() results.values = listFilter return results; } override fun publishResults(p0: CharSequence?, p1: Filter.FilterResults?) { listdataSearch.clear() listdataSearch.addAll(p1?.values as Collection<ExampleData>) notifyDataSetChanged() } } } } |
item_layout
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:elevation="5dp" app:cardCornerRadius="4dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="4dp"> <ImageView android:id="@+id/image_view" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/ic_launcher" android:padding="2dp" /> <TextView android:id="@+id/text_view1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toEndOf="@+id/image_view" android:text="Line 1" android:textColor="@android:color/black" android:textSize="20sp" android:textStyle="italic" /> <TextView android:id="@+id/text_view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/text_view1" android:layout_marginStart="8dp" android:layout_toEndOf="@+id/image_view" android:text="Line 2" android:textSize="15sp" /> </RelativeLayout> </androidx.cardview.widget.CardView> |