'Filter Listview using Searchview with Custom Adapter in Kotlin
I'm new to android and would like to get some help. I have created a list view in my android and have implemented a search filter method using searchview to search for the name of the image from the database SQLite. However, my list of data does not show up when my search filter method is implemented and not sure what went wrong.
I have searched on many sites to compare the examples but most of the them are either in java or does not fit my program. Your help is greatly appreciated. Here are the codes:
TouristSpotPage:
class TouristSpotPage : AppCompatActivity() {
var myTouristSpotList: ListView? = null
var touristSpotList = ArrayList<DataList>()
var customAdapter: CustomAdapter? = null
var touristSpotImageView: ImageView? = null
var mDatabaseHelper: DatabaseHelper? = null
var name: String? = null
lateinit var image: ByteArray
var id = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.tourist_spot_page)
myTouristSpotList = findViewById(R.id.touristSpotListView)
touristSpotList = ArrayList()
customAdapter =
CustomAdapter(this, R.layout.tourist_spot_custom_list_layout, touristSpotList)
myTouristSpotList!!.adapter = customAdapter
mDatabaseHelper = DatabaseHelper(this)
addSomeData() //<<<<<<<<<< FOR ADDING DATA MANUALLY
val data = mDatabaseHelper!!.getData("SELECT * FROM tourist_spot_table")
touristSpotList.clear()
while (data.moveToNext()) {
id = data.getInt(0)
name = data.getString(1)
image = data.getBlob(2)
touristSpotList.add(DataList(id, name!!, image))
Log.i("image", String(image))
}
search() // Search function
data.close() //CLOSE CURSOR WHEN DONE WITH IT
customAdapter!!.notifyDataSetChanged()
returnHomepage()
}
private fun addSomeData() {
mDatabaseHelper!!.writableDatabase.delete(
DatabaseHelper.TABLE_TOURIST_SPOT,
null,
null
) //<<<<<<<<<< Delete all pets
mDatabaseHelper!!.addTouristSpotImageFromAssets(
"Petronas Twin Tower",
"malaysia-top-attractions-petronas-twin-towers.jpg"
)
mDatabaseHelper!!.addTouristSpotImageFromAssets(
"Batu Caves",
"malaysia-top-attractions-batu-caves-selangor.jpg"
)
mDatabaseHelper!!.addTouristSpotImageFromAssets(
"Cameron Highland",
"malaysia-top-attractions-cameron-highlands.jpg"
)
}
private fun returnHomepage() {
val returntoHomepage = findViewById<ImageView>(R.id.return_button_icon)
returntoHomepage.setOnClickListener {
val intent = Intent(this, Homepage::class.java)
startActivity(intent)
}
}
// Search function for searching name from the database
private fun search()
{
val lv = findViewById<ListView>(R.id.touristSpotListView)
val searchBar = findViewById<SearchView>(R.id.SearchBar)
searchBar.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String?): Boolean {
if(TextUtils.isEmpty(newText)){
Log.i(TAG,"Search Name")
(lv.adapter as CustomAdapter?)?.filterName("")
lv.clearTextFilter()
}else {
if (newText != null) {
Log.i("Searched", newText)
(lv.adapter as CustomAdapter?)?.filterName(newText)
}
}
return true
}
override fun onQueryTextSubmit(query: String?): Boolean {
return false
}
})
}
}
CustomAdapter:
class CustomAdapter(private val context: Context,private val layout: Int,
private val recordList: ArrayList<DataList>) :
BaseAdapter()
{
override fun getCount(): Int {
return recordList.size
}
override fun getItem(position: Int): Any {
return recordList[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
private inner class ViewHolder {
var touristSpotImageView: ImageView? = null
var touristSpotTextView: TextView? = null
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
var v = convertView
var holder = ViewHolder()
if (v == null) {
val layoutInflater =
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
v = layoutInflater.inflate(layout, null)
holder.touristSpotImageView = v.findViewById(R.id.touristSpotImageView)
holder.touristSpotTextView = v.findViewById(R.id.touristSpotTextView)
v.tag = holder
} else {
holder = v.tag as ViewHolder
}
val datalist = recordList[position]
holder.touristSpotTextView!!.text = datalist.name
val recordImage = datalist.image
val bitmap = BitmapFactory.decodeByteArray(recordImage, 0, recordImage.size)
holder.touristSpotImageView!!.setImageBitmap(bitmap)
return v
}
var filteredList = ArrayList<DataList>()
fun filterName(Text: String) { // Filter Class
Log.i("searched inside:", Text)
var Text = Text
Text = Text.lowercase(Locale.getDefault())
if (Text.isEmpty()) {
filteredList = recordList
} else {
for (touristName in recordList) {
if (touristName.name.lowercase(Locale.getDefault())?.contains(Text)!!) {
filteredList = listOf(touristName) as ArrayList<DataList>
}
}
}
notifyDataSetChanged()
}
}
DatabaseHelper
class DatabaseHelper(context: Context) :
SQLiteOpenHelper(context, DBNAME, null, DBVERSION) {
var mDB: SQLiteDatabase = this.writableDatabase
var mContext: Context = context
override fun onCreate(db: SQLiteDatabase) {
val tourist_spot_table = "CREATE TABLE IF NOT EXISTS " + TABLE_TOURIST_SPOT + "(" +
COLUMN_TOURIST_SPOT_ID + " INTEGER PRIMARY KEY, " +
COLUMN_TOURIST_SPOT_NAME + " TEXT," +
COLUMN_TOURIST_SPOT_IMAGE + " BLOB DEFAULT x'00'," +
COLUMN_TOURIST_SPOT_IMAGEPATH + " TEXT DEFAULT ''" +
")"
db.execSQL(tourist_spot_table)
}
companion object {
const val DBNAME = "tourists.db"
const val DBVERSION = 1
const val TABLE_TOURIST_SPOT = "tourist_spot_table"
const val COLUMN_TOURIST_SPOT_ID = BaseColumns._ID
const val COLUMN_TOURIST_SPOT_NAME = "name"
const val COLUMN_TOURIST_SPOT_IMAGE = "image"
const val COLUMN_TOURIST_SPOT_IMAGEPATH = "imagepath"
}
override fun onUpgrade(db: SQLiteDatabase, i: Int, i1: Int) {}
/**
* NOT USED
* @param touristSpotName
* @return
*/
fun addTouristSpot(touristSpotName: String?, touristSpotImage: Blob?): Long {
val cv = ContentValues()
cv.put(COLUMN_TOURIST_SPOT_NAME, touristSpotName)
//cv.put(COLUMN_PET_IMAGE,touristSpotImage)
return mDB.insert(TABLE_TOURIST_SPOT, null, cv)
}
fun addTouristSpotImageFromAssets(touristSpotName: String?, touristSpotImage: String): Long {
var touristspotimage = ByteArray(0)
var image_size = 0
try {
val `is`: InputStream = mContext.getAssets().open(touristSpotImage)
image_size = `is`.available()
touristspotimage = ByteArray(image_size)
`is`.read(touristspotimage)
`is`.close()
} catch (e: IOException) {
}
val cv = ContentValues()
cv.put(COLUMN_TOURIST_SPOT_NAME, touristSpotName)
if (image_size > 0) {
cv.put(COLUMN_TOURIST_SPOT_IMAGE, touristspotimage)
}
return mDB.insert(TABLE_TOURIST_SPOT, null, cv)
}
fun getData(query: String?): Cursor {
return mDB.rawQuery(query, null)
}
}
tourist_spot_page.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="130dp"
android:background="@color/light_blue"
android:orientation="vertical">
<ImageView
android:id="@+id/return_button_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/return_icon"
android:layout_margin="15dp"
>
</ImageView>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/title"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/black"
android:textAlignment="center"
/>
</LinearLayout>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_box_shape"
android:elevation="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|right"
android:layout_marginRight="20dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center|right">
<SearchView
style="@style/MaterialSearchBarLight"
android:id="@+id/SearchBar"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_margin="5dp" />
</LinearLayout>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<ListView
android:id="@+id/touristSpotListView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
<TextView
android:id="@+id/emptyTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/noresult"
android:textSize="20sp"
android:visibility="gone">
</TextView>
</LinearLayout>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
