Welcome to kotlin listview searchview tutorial example.
In this article, you will learn how to implement search filter functionality for listview using the searchview.
Search filter is very basic functionality and you will need this in almost every case where members of listview is very high.
Java Code
If you are looking for the same tutorial in JAVA language then read : Android SearchView ListView in JAVA
First of all, see the below output result of this example.
Step 1. New Project For Kotlin
In this step ,you need to make a new project in android studio. Here, you need to add kotlin support or select project language as a kotlin.
Along with adding kotlin support, you also need to select empty activity as a default activity.
Step 2. Separate Row file for Listview
Let us make a new layout file that will create a specific view for each listview item.
Inside, res->layout directory, add a new XML layout file and give it a name like lv_item.xml
You should add the following source snippet in lv_item.xml file.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dp"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
Step 3. Making Model File
Now create a new Kotlin file or class and give it a name like MovieNames.kt
Below is the source code lines for MovieNames.kt file.
class MovieNames{ private val movieName: String constructor(movieName: String){ //code this.movieName = movieName } fun getAnimalName(): String { return this.movieName } }
This MovieNames.kt file is working as a model class for listview.
We will create an object of this class for each listview row item. We will do this in the Main Activity.kt class.
See the source code of this class. It contains one constructor. There is one string variable in this constructor.
Above the constructor, we have defined one simple string variable. We will assign the value of the constructor string variable to the simple string variable.
Then there is a method called getAnimalName()
This getAnimalName() method will return the value of the simple string variable.
Step 4. Writing the Adapter Class
Make a new kotlin class and set it’s name as ListViewAdapter.kt
In this ListViewAdapter.kt class, write down the following source code lines
import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.TextView import java.util.ArrayList import java.util.Locale class ListViewAdapter( // Declare Variables internal var mContext: Context ) : BaseAdapter() { internal var inflater: LayoutInflater private val arraylist: ArrayList<MovieNames> init { inflater = LayoutInflater.from(mContext) this.arraylist = ArrayList() this.arraylist.addAll(MainActivity.movieNamesArrayList) } inner class ViewHolder { internal var name: TextView? = null } override fun getCount(): Int { return MainActivity.movieNamesArrayList.size } override fun getItem(position: Int): MovieNames { return MainActivity.movieNamesArrayList[position] } override fun getItemId(position: Int): Long { return position.toLong() } override fun getView(position: Int, view: View?, parent: ViewGroup): View { var view = view val holder: ViewHolder if (view == null) { holder = ViewHolder() view = inflater.inflate(R.layout.lv_item, null) // Locate the TextViews in listview_item.xml holder.name = view!!.findViewById(R.id.name) as TextView view.tag = holder } else { holder = view.tag as ViewHolder } // Set the results into TextViews holder.name!!.setText(MainActivity.movieNamesArrayList[position].getAnimalName()) return view } // Filter Class fun filter(charText: String) { var charText = charText charText = charText.toLowerCase(Locale.getDefault()) MainActivity.movieNamesArrayList.clear() if (charText.length == 0) { MainActivity.movieNamesArrayList.addAll(arraylist) } else { for (wp in arraylist) { if (wp.getAnimalName().toLowerCase(Locale.getDefault()).contains(charText)) { MainActivity.movieNamesArrayList.add(wp) } } } notifyDataSetChanged() } }
An adapter class will bind the data source with the listview. Here, our data source will be the arraylist with the objects of MovieNames.kt class. We are getting this data source from below line
this.arraylist.addAll(MainActivity.movieNamesArrayList)
Main Activity contains the movieNamesArrayList as a public access specifier. So we can use it in this adapter class.
See the following source lines
override fun getView(position: Int, view: View?, parent: ViewGroup): View { var view = view val holder: ViewHolder if (view == null) { holder = ViewHolder() view = inflater.inflate(R.layout.lv_item, null) // Locate the TextViews in listview_item.xml holder.name = view!!.findViewById(R.id.name) as TextView view.tag = holder } else { holder = view.tag as ViewHolder } // Set the results into TextViews holder.name!!.setText(MainActivity.movieNamesArrayList[position].getAnimalName()) return view }
This method will create the view for each child row of listview.
It will inflate the lv_item.xml file as the base of creating look and feel of row item.
lv_item.xml file contains one text view. Compiler will use movieNamesArrayList o set the name of the movie in this text view.
Now see the following lines
// Filter Class fun filter(charText: String) { var charText = charText charText = charText.toLowerCase(Locale.getDefault()) MainActivity.movieNamesArrayList.clear() if (charText.length == 0) { MainActivity.movieNamesArrayList.addAll(arraylist) } else { for (wp in arraylist) { if (wp.getAnimalName().toLowerCase(Locale.getDefault()).contains(charText)) { MainActivity.movieNamesArrayList.add(wp) } } } notifyDataSetChanged() }
A filter() function is the heart of this search view listview kotlin tutorial.
This function will get the search query via it’s parameter. Then it will save this query in one separate variable.
Then clear the movieNamesArrayList . Now it will check how many words are there in search query. If zero then it will again fill all the movie names in movieNamesArrayList
But if not zero then it will create one for loop. In every iteration of for loop, compiler will get the movie name and will check if it contains the words of search query. If yes then it will simply add this movie name in movieNamesArrayList otherwise not.
Step 5. Main Activity Writings
You should have two files for main activity : activity_main.xml and MainActivity.kt
In your activity_main.xml file, add the following code snippet
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <SearchView android:id="@+id/search" android:layout_width="fill_parent" android:layout_height="wrap_content" android:iconifiedByDefault="false"> <requestFocus /> </SearchView> <ListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@+id/search" /> </RelativeLayout>
One search view and one listview is there in this XML file. Search is above the listview.
Now in MainActivity.kt file, write down the below source lines
import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.widget.AdapterView import android.widget.ListView import android.widget.SearchView import android.widget.Toast import java.util.ArrayList class MainActivity : AppCompatActivity(), SearchView.OnQueryTextListener { // Declare Variables private var list: ListView? = null private var adapter: ListViewAdapter? = null private var editsearch: SearchView? = null private var moviewList: Array<String>? = null public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Generate sample data moviewList = arrayOf( "Xmen", "Titanic", "Captain America", "Iron man", "Rocky", "Transporter", "Lord of the rings", "The jungle book", "Tarzan", "Cars", "Shreck" ) // Locate the ListView in listview_main.xml list = findViewById(R.id.listview) as ListView movieNamesArrayList = ArrayList() for (i in moviewList!!.indices) { val movieNames = MovieNames(moviewList!![i]) // Binds all strings into an array movieNamesArrayList.add(movieNames) } // Pass results to ListViewAdapter Class adapter = ListViewAdapter(this) // Binds the Adapter to the ListView list!!.adapter = adapter // Locate the EditText in listview_main.xml editsearch = findViewById(R.id.search) as SearchView editsearch!!.setOnQueryTextListener(this) list!!.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> Toast.makeText( this@MainActivity, movieNamesArrayList[position].getAnimalName(), Toast.LENGTH_SHORT ).show() } } override fun onQueryTextSubmit(query: String): Boolean { return false } override fun onQueryTextChange(newText: String): Boolean { adapter!!.filter(newText) return false } companion object { var movieNamesArrayList = ArrayList<MovieNames>() } }
Understand Main Ativity
Let us read each line from above snippet.
First of all, see the below code
// Declare Variables private var list: ListView? = null private var adapter: ListViewAdapter? = null private var editsearch: SearchView? = null private var moviewList: Array<String>? = null
Above snippet is declaring four variables. First one is listview object, second one is adapter object, third is searchview object and last one is String arraylist.
Now see the following lines
moviewList = arrayOf( "Xmen", "Titanic", "Captain America", "Iron man", "Rocky", "Transporter", "Lord of the rings", "The jungle book", "Tarzan", "Cars", "Shreck" )
We are just filling the string array variable with the names of the movies. This will be the primary data source.
Now look at the following code lines
movieNamesArrayList = ArrayList() for (i in moviewList!!.indices) { val movieNames = MovieNames(moviewList!![i]) // Binds all strings into an array movieNamesArrayList.add(movieNames) }
movieNamesArrayList is the arraylist with the objects of the MovieNames classes.
First line is initializing the variable. Then there is one for loop.
Every iteration of for loop will make a new object of MovieNames class. In the parameter, we will add the movie name from string array variable moviewList
After creating an object, we will add this object into movieNamesArrayList . Thus one iteration of for loop is complete.
Number of for loop iterations are equal to the number of members in the string array variable moviewList
Now focus on the below code
// Pass results to ListViewAdapter Class adapter = ListViewAdapter(this) // Binds the Adapter to the ListView list!!.adapter = adapter
First line is initializing the adapter object.
Second one is simply binding the adapter to the listview.
Now read the below code
editsearch = findViewById(R.id.search) as SearchView editsearch!!.setOnQueryTextListener(this)
First one is finding the searchview from id and second one is defining a query listener.
When you define the search query listener, you need to override two functions and they are as the following
override fun onQueryTextSubmit(query: String): Boolean { return false } override fun onQueryTextChange(newText: String): Boolean { adapter!!.filter(newText) return false }
When the user types the search query, compiler will run the second function onQueryTextChanged() and it will execute the filter() function which is written in the ListViewAdapter.kt class.
filter() function will send the search query as it’s parameter.
Now see the below
list!!.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> Toast.makeText( this@MainActivity, movieNamesArrayList[position].getAnimalName(), Toast.LENGTH_SHORT ).show() }
Compiler will run the above code when the user clicks the listview. It will pop up one toast and will write the name of the movie in the toast.
Download Source For This Example
https://github.com/demonuts/kotlin-listview-searchview-android-tutorial-example