I have tried to implement search functionality in the recycler view.for that I have written below code in My "Main.kt" class
search functionality is working fine for me,
the issue is when I am searching the item from the list and clicking on that item I am getting the wrong position.
please help me with this issue.
adapter = DynamicListAdapter(dynamicList)
dynamic_list_recyclerview.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL,false) as RecyclerView.LayoutManager
dynamic_list_recyclerview.adapter = adapter
adapter!!.setRecyclerViewItemClickLister(this)
i have taken edit text and added the addTextChangedListener
edt_search_dynamic.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(editable: Editable?) {
filter(editable.toString())
}
})
fun filter(text : String){
var filteredList = mutableListOf<DynamicModel>()
for(list in dynamicList){
if(list.vehicleno.toLowerCase().contains(text.toLowerCase())){
filteredList.add(list)
}
}
adapter?.filterList(filteredList)
}
and this is my adapter class
class DynamicListAdapter (var dynamiclist : List<DynamicModel>) : RecyclerView.Adapter<DynamicListAdapter.DynamicViewHolder>() {
var recyclerViewOnItemClickListener : RecyclerViewOnItemClickListener? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DynamicViewHolder {
val inflatedView = LayoutInflater.from(parent.context)
.inflate(R.layout.singlerowdynamiclist,parent,false)
return DynamicViewHolder(inflatedView,dynamiclist)
}
override fun getItemCount(): Int {
return dynamiclist.size
}
override fun onBindViewHolder(holder: DynamicViewHolder, position: Int) {
holder.bindItem(dynamiclist[position])
}
inner class DynamicViewHolder(itemView : View, var dynamiclists : List<DynamicModel>) : RecyclerView.ViewHolder(itemView), View.OnClickListener
{
private var txtStatus : TextView? = null
init {
txtStatus = itemView.findViewById(R.id.txtStatus)
itemView.setOnClickListener(this)
}
fun bindItem(dynamiclist : DynamicModel){
txtStatus?.text = dynamiclist.vehiclestatus
}
override fun onClick(view: View?) {
when(view){
itemView -> if(recyclerViewOnItemClickListener!= null){
recyclerViewOnItemClickListener!!.onItemClick(adapterPosition,view)
}
}
}
}
// method of outer class
fun setRecyclerViewItemClickLister(onRecyclerviewItemClickListener : RecyclerViewOnItemClickListener){
this.recyclerViewOnItemClickListener = onRecyclerviewItemClickListener
}
// for filter the list
fun filterList(dymaniclist : List<DynamicModel>){
this.dynamiclist = dymaniclist
notifyDataSetChanged()
}
}
and this is the interface which I have implemented in my Main.kt class
interface RecyclerViewOnItemClickListener {
fun onItemClick(position : Int, view: View)
}
You won't get the desired position (the position from the unfiltered list) after applying your filters, because you lose that information when creating a new filtered list and putting it inside the
DynamicListAdapter.Let's say inside the
adapterwe have a list of the following items:Now let's use your
filtermethod:This ends with replacing the old
dynamicListinside theDynamicListAdapterwith a completely newfilteredList, which looks like this:Now when clicking the
#2 AByou will get position of value1(not desired2) as it is the item's index in the newfilteredList.There are multiple ways of how to achieve what you want, but if you only want data from the clicked item, just return the object instead of its position on the item click:
However if you need to return the position and the above is not an option, I would suggest leaving the original list in the
adapterand letting it handle filtering by itself, for example: