简体   繁体   中英

Recyclerview Filter not working in kotlin android

I trying filtering recycler view with filter function in adapter but it's not working.

I have added searchview listener like this:

init(){
binding.svCategory.setOnQueryTextListener(this)
}

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

    override fun onQueryTextChange(newText: String?): Boolean {
        adapterCategories.getFilter().filter(newText)
        return true
    }

and here is my adapter that i have created:

class CategoriesAdapter(
    var context: Context,
    var listCategories: ArrayList<Categories>,
    var onGalleryClick: (Any) -> Unit,
    var onCameraClick: (Any) -> Unit,
    var onDeleteClick: (Any) -> Unit
) :
    RecyclerView.Adapter<CategoriesAdapter.CategoriesViewHolder>(), Filterable {

    private var filterList: ArrayList<Categories> = listCategories

    init {
        filterList = listCategories
    }

    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): CategoriesViewHolder {
        val view = LayoutInflater.from(viewGroup.context)
            .inflate(R.layout.rv_category_item, viewGroup, false)

        return CategoriesViewHolder(view)
    }

    override fun onBindViewHolder(holder: CategoriesViewHolder, position: Int) {

        holder.tvCategoryName.text = listCategories[position].name
        if (listCategories[position].imageUri != null) {
            Glide
                .with(context)
                .load(Uri.parse(listCategories[position].imageUri))
                .centerCrop()
                .placeholder(R.drawable.add)
                .into(holder.ivImage)
        }
        if (listCategories[position].imageUri.isNullOrEmpty()) {
            holder.ivDelete.visibility = View.GONE
        } else {
            holder.ivDelete.visibility = View.VISIBLE
        }
        holder.ivGallery.setOnClickListener {
            onGalleryClick(position)
        }

        holder.ivCamera.setOnClickListener {
            onCameraClick(position)
        }
        holder.ivDelete.setOnClickListener {
            onDeleteClick(position)
        }
    }

    override fun getItemCount(): Int {
        return filterList.size
    }

    override fun getFilter(): Filter {
        return object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults {
                val charSearch = constraint.toString()
                filterList = if (charSearch.isEmpty()) {
                    listCategories
                } else {
                    val resultList = ArrayList<Categories>()
                    for (row in listCategories) {
                        if (row.name.toLowerCase().contains(constraint.toString().toLowerCase())) {
                            resultList.add(row)
                        }
                    }
                    resultList
                }
                val filterResults = FilterResults()
                filterResults.values = filterList
                return filterResults
            }

            override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                filterList = results?.values as ArrayList<Categories>
                notifyDataSetChanged()
            }
        }
    }

    class CategoriesViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        var tvCategoryName: AppCompatTextView = view.findViewById(R.id.tvCategoryName)
        var ivImage: AppCompatImageView = view.findViewById(R.id.ivImage)
        var ivGallery: AppCompatImageView = view.findViewById(R.id.ivGallery)
        var ivCamera: AppCompatImageView = view.findViewById(R.id.ivCamera)
        var ivDelete: AppCompatImageView = view.findViewById(R.id.ivDelete)
    }

}

but it doesn't filter item properly, it shows the right count but doesn't show proper items in the recyclerview,

So what to do for this issue? Can anyone help?

Thanks in advance.

inside onBindViewHolder you are using listCategories[position] instead of filterList[position] . on start it have same content like original listCategories ( init{} call), but after filtering getItemCount returns size of filtered results, but in onBindViewHolder still drawing listCategories array. work only on filterList and keep listCategories untouched, usable only on start (filling filterList ) and when restoring original list (eg when query removed)

PS. work only on some temporary array inside performFiltering , currently you are changing filterList strictly in line filterList = if . just add var before filterList . this will make this array only locally available, it will be attached to filterResults.values and then updated in publishResults (these functions are called in different Thread s)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM