Android Searchview with RecyclerView Example | Android studio

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
  • Use SearchView inside Activity
  • Apply Search Filter inside Adapter

 

Recyclerview with SearchView widget

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>