Search code examples
androidandroid-recyclerviewandroid-filterable

Why filtering property not work for search bar in android?


I have a simple android project, there is a recycler view in fragment for user list, and I want to use search bar for those users, that is why I am using filtering for search the user in list view, everything is work but when I search user name, nothing change, and filtering property not work for users name. Any idea will be appreciated.

GameAdapter:

class GameAdapter(
    private val userId: String,
      var chatList: ArrayList<Game>

): RecyclerView.Adapter<GameAdapter.GamesHolder>(), Filterable {

    private var clickListener: ClickListener? = null
        var filteredUserDataList: MutableList<Game>

    inner class GamesHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener, View.OnLongClickListener {
        val textGameTitle: TextView = view.findViewById(R.id.textUsername)
     
    }
   override fun onBindViewHolder(holder: GamesHolder, position: 
   Int) {
    val game = filteredUserDataList[position]
  holder.textGameTitle.text = 
 game.getGameName(userId).toString()
    }

  override fun getItemCount(): Int {
    return filteredUserDataList.size
}
override fun getFilter(): Filter {
    return filter
}

private var filter = object : Filter() {

    override fun performFiltering(keyword: CharSequence): FilterResults {
        val filtereddata = java.util.ArrayList<Game>()
        if (keyword.toString().isEmpty()) filtereddata.addAll(gameList) else {
            for (obj in gameList) {
                if (obj.getGameName(userId).toLowerCase()
                        .contains(keyword.toString().toLowerCase())
                ) filtereddata.add(obj)
            }
        }
        val results = FilterResults()
        results.values = filtereddata
        return results
    }

  
    override fun publishResults(constraint: CharSequence, results: FilterResults) {
        gameList.clear()
        gameList.addAll((results.values as ArrayList<Game>))
        notifyDataSetChanged()
    }

    init {
        filteredUserDataList = gameList
    }
}

fun getItem(index: Int): Game {
    return filteredUserDataList[index]
} 

GameFragment:

class GameFragment : Fragment() {

    lateinit var recyclerViewGame: RecyclerView

    var searchView: EditText? = null
    var search: CharSequence = ""

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val view = inflater.inflate(R.layout.fragment_games, container, false)

        recyclerViewGame = view.findViewById(R.id.game_list)

        configureRecycler(gameList)

        return view

    }

    private fun configureRecycler(games: ArrayList<Game>) {
        val userId = userPresenter.getGame().id
        val gamesAdapter = context?.let {
            GameAdapter(userId, it, games)
        }

        searchView = view?.findViewById(R.id.search_bar)

        searchView?.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
            override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
                gamesAdapter.filter.filter(charSequence)
                search = charSequence
            }
            override fun afterTextChanged(editable: Editable) {}
        })
     } }

Solution

  • I can see these things

    1. filteredUserDataList should be initialized with gameList

    2. change

      override fun getItemCount() = gameList.size

      to

      override fun getItemCount() = filteredUserDataList.size

    3. and remember that filteredUserDataList is the main list and the actual gameList is just to maintain the original data if the user clears or change the search query