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)
}