Home > Net >  Issue Ranking the user when Searched via Search Box in Recycler View
Issue Ranking the user when Searched via Search Box in Recycler View

Time:12-16

I am trying to figure out how to display the filtered(searched) list with the correct rank as displayed in the recycle view at the beginning ...

So, what i am trying to say is: (Issue Link)
https://mega.nz/file/cksjAQgD#ofyhLQOd3KW4nuw2NShrPLDncj4Fz6hSoWdN5jVbERc
When i search the the user from the search box the user rank should be displayed as the rank assigned in the recycle view (without searched)

Here is my code

class LeaderboardFragment : BaseFragment() {

    private lateinit var list : ArrayList<User>
    private lateinit var binding: FragmentLeaderboardBinding
    private lateinit var filteredLeaderBoardList:ArrayList<User>
    private lateinit var leaderBoardUserList:ArrayList<User>
    companion object{
        var list=ArrayList<User>()
    }
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding=FragmentLeaderboardBinding.inflate(inflater,container,false)
        binding.toolbarDashboard.inflateMenu(R.menu.leaderboard_top)
        activity?.window!!.statusBarColor = requireActivity().getColor(R.color.dark_green)
        leaderBoardUserList = kotlin.collections.ArrayList<User>()
        //LeaderBoardSearchFunctionality
        binding.searchBox.clearFocus()
        binding.searchBox.setOnQueryTextListener(object:OnQueryTextListener{
            override fun onQueryTextSubmit(query: String?): Boolean {

                return false

            }

            override fun onQueryTextChange(newText: String?): Boolean {
                filterLeaderBoardList(newText)
                return true
            }

        })

//         list=ArrayList<User>()
//        list.add(User("1","Pratyush","[email protected]","8.4"))
//        list.add(User("2","Ayush","[email protected]","7.2"))
//        list.add(User("3","Abhiram","[email protected]","6.8"))
//        list.add(User("4","Aditya","[email protected]","5.3"))
//        list.add(User("5","Samyak","[email protected]","5.1"))
//        list.add(User("6","Rahul","[email protected]","4.9"))
//        list.add(User("7","Ankur","[email protected]","3.0"))
//        list.add(User("8","Adiii","[email protected]","2.5"))
//        list.add(User("9","Prince","[email protected]","1.7"))
//        list.add(User("10","Ritik","[email protected]","0.8"))


        return binding.root
    }

    private fun filterLeaderBoardList(newText: String?) {
        filteredLeaderBoardList = ArrayList<User>()
        for(item in leaderBoardUserList){
            if(item.name.lowercase().contains(newText!!.lowercase()))
            {
                filteredLeaderBoardList.add(item)
            }
        }
        if(filteredLeaderBoardList.isEmpty()){
            showErrorSnackBar("No User Found",true)
        }else{
            binding.rvLeaderboard.adapter=LeaderboardAdapter(requireContext(),filteredLeaderBoardList)
        }
    }

    fun getLeaderBoard(userList: ArrayList<User>) {
        userList.sortByDescending { it.distance.toDouble() }
        hideProgressDialog()
        binding.rvLeaderboard.adapter=LeaderboardAdapter(requireContext(),userList)
        binding.rvLeaderboard.layoutManager=LinearLayoutManager(activity,LinearLayoutManager.VERTICAL,false)
    }
    fun getUserList(userList:ArrayList<User>){

        //filter list issue pratyush singh is at bottom with 7.9km should at pos 2
        leaderBoardUserList = userList
        getTopUser(userList)
    }

    override fun onResume() {
        super.onResume()
        showProgressDialog()
        FirestoreClass().getLeaderboardFragment(this)
    }

    private fun getTopUser(userList: ArrayList<User>) {
        binding.nameOfUser.text = userList.first().name
        binding.emailOfUser.text = userList.first().email
        binding.distanceCovered.text = userList.first().distance " km"
    }
}

LeaderboardAdapter.kt

class LeaderboardAdapter(val context: Context, private var list: ArrayList<User>) :
    RecyclerView.Adapter<LeaderboardAdapter.LeaderViewHolder>() {
    inner class LeaderViewHolder(val binding: ItemLeaderboardBinding) :
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LeaderViewHolder {
        return LeaderViewHolder(
            ItemLeaderboardBinding.inflate(
                LayoutInflater.from(context),
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: LeaderViewHolder, position: Int) {
        val model = list[position]
        Log.d("listelements","$model")
        holder.binding.positionOfUser.text = (position 1).toString() " . "
        holder.binding.nameOfUser.text = model.name
        holder.binding.emailOfUser.text = model.email
        holder.binding.distanceCovered.text = model.distance
    }

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

//    fun setLeaderBoardQuery(filteredList:ArrayList<User>){
//        this.list = filteredList
//        notifyDataSetChanged()
//    }

}

Can anyone just help me figuring this out!

CodePudding user response:

As you can see, you are using the position of the user as their rank. What you should do instead is have the rank (position) in the data class of that person and show that one instead. Otherwise, the LeaderboardAdapter will produce incorrect data. In your case:

class LeaderboardAdapter(val context: Context, private var list: ArrayList<User>) :
    RecyclerView.Adapter<LeaderboardAdapter.LeaderViewHolder>() {
    inner class LeaderViewHolder(val binding: ItemLeaderboardBinding) :
        RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LeaderViewHolder {
        return LeaderViewHolder(
            ItemLeaderboardBinding.inflate(
                LayoutInflater.from(context),
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: LeaderViewHolder, position: Int) {
        val model = list[position]
        Log.d("listelements", "$model")
        // As you can see, we use model's position variable instead of position argument
        holder.binding.positionOfUser.text = model.position.toString()   " . "
        holder.binding.nameOfUser.text = model.name
        holder.binding.emailOfUser.text = model.email
        holder.binding.distanceCovered.text = model.distance
    }

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

//    fun setLeaderBoardQuery(filteredList:ArrayList<User>){
//        this.list = filteredList
//        notifyDataSetChanged()
//    }

}

On other note, I'd highly recommend not setting the adapter on each search but instead change objects inside the adapter instead. Even better if you use DiffUtil

EDIT:

I'd change this getLeaderBoard() function in LeaderboardFragment:

fun getLeaderBoard(userList: ArrayList<User>) {
    val sortedList = userList.sortByDescending { it.distance.toDouble() }
        .mapIndexed { index, item -> item.copy(position = index   1) }
    hideProgressDialog()
    binding.rvLeaderboard.adapter = LeaderboardAdapter(requireContext(), sortedList)
    binding.rvLeaderboard.layoutManager =
        LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
}
  • Related