Search Filter on Recycler View (Android)

Image for post
Image for post
Android Dynamic Search Adapter

Pre-Requisites:

Let’s get Started

class SearchAdapter1(private val mutableList: MutableList<SearchModel1>) :
DynamicSearchAdapter<SearchModel1>(mutableList) {


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val textView = TextView(parent.context)
return ViewHolder(textView)
}

override fun getItemCount(): Int {
return mutableList.count()
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val tv = holder.containerView as TextView
tv.text = mutableList[position].data

}


}
class SearchAdapter2(private val mutableList: MutableList<SearchModel2>) :
DynamicSearchAdapter<SearchModel2>(mutableList) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val textView = TextView(parent.context)
return ViewHolder(textView)
}

override fun getItemCount(): Int {
return mutableList.count()
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val tv = holder.containerView as TextView
tv.text = mutableList[position].data

}


}
abstract class DynamicSearchAdapter<T : DynamicSearchAdapter.Searchable>(private val searchableList: MutableList<T>) :
RecyclerView.Adapter<ViewHolder>(), Filterable {

// Single not-to-be-modified copy of original data in the list.
private val originalList = ArrayList(searchableList)
// a method-body to invoke when search returns nothing. It can be null.
private var onNothingFound: (() -> Unit)? = null

/**
* Searches a specific item in the list and updates adapter.
* if the search returns empty then onNothingFound callback is invoked if provided which can be used to update UI
*
@param s the search query or text. It can be null.
*
@param onNothingFound a method-body to invoke when search returns nothing. It can be null.
*/
fun search(s: String?, onNothingFound: (() -> Unit)?) {
this.onNothingFound = onNothingFound
filter.filter(s)

}

override fun getFilter(): Filter {
return object : Filter() {
private val filterResults = FilterResults()
override fun performFiltering(constraint: CharSequence?): FilterResults {
searchableList.clear()
if (constraint.isNullOrBlank()) {
searchableList.addAll(originalList)
} else {
val searchResults = originalList.filter { it.getSearchCriteria().contains(constraint) }
searchableList
.addAll(searchResults)
}
return filterResults.also {
it
.values = searchableList
}
}

override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
// no need to use "results" filtered list provided by this method.
if (searchableList.isNullOrEmpty())
onNothingFound?.invoke()
notifyDataSetChanged()

}
}
}

interface Searchable {
/** This method will allow to specify a search string to compare against
your search this can be anything depending on your use case.
*/
fun getSearchCriteria(): String
}


}
class SearchModel1(val data: String) : DynamicSearchAdapter.Searchable {


override fun getSearchCriteria(): String {
return data
}
}
class SearchModel2(val data: String) : DynamicSearchAdapter.Searchable {


override fun getSearchCriteria(): String {
return data
}
}
class SampleActivity2 : AppCompatActivity(), SearchView.OnQueryTextListener {


private lateinit var searchAdapter3: SearchAdapter3

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.fragment_main)
rv.layoutManager = LinearLayoutManager(this)
searchAdapter3 = SearchAdapter3(mutableListOf<SearchModel3>().populateWithUUIDSM3())
rv.adapter = searchAdapter3
searchV.setOnQueryTextListener(this)

}

override fun onQueryTextChange(newText: String?): Boolean {
search(newText)
return true
}

override fun onQueryTextSubmit(query: String?): Boolean {
search(query)
return true
}

private fun search(s: String?) {
searchAdapter3.search(s) {
// update UI on nothing found
Toast.makeText(this, "Nothing Found", Toast.LENGTH_SHORT).show()
}
}

How to run ?

Last Step

Software Engineer II (Android) @ Careem || Fitness Freak for 9 years

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store