RecyclerView搜索筛选后保持用户初始排名显示问题求助
解决方案
核心思路是给每个用户记录初始排序后的固定排名,而非依赖RecyclerView的列表位置计算排名。这样无论怎么筛选,每个用户的排名都会和初始排行榜一致。
步骤1:给User类添加排名字段
在你的User数据类中新增rank属性,用来存储用户在初始排行榜中的固定排名:
data class User( val id: String, val name: String, val email: String, val distance: String, var rank: Int = 0 // 新增排名字段 )
步骤2:排序后为每个用户分配正确排名
修改LeaderboardFragment的getLeaderBoard方法,排序完成后遍历列表,给每个用户设置对应的初始排名:
fun getLeaderBoard(userList: ArrayList<User>) { // 按距离降序排序 userList.sortByDescending { it.distance.toDouble() } // 为每个用户设置初始排名(从1开始) userList.forEachIndexed { index, user -> user.rank = index + 1 } // 保存带排名的完整列表,后续筛选基于此列表 leaderBoardUserList = userList hideProgressDialog() binding.rvLeaderboard.adapter = LeaderboardAdapter(requireContext(), userList) binding.rvLeaderboard.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) getTopUser(userList) }
步骤3:修改Adapter显示固定排名
修改LeaderboardAdapter的onBindViewHolder方法,直接使用用户的rank字段,不再依赖当前列表的position:
override fun onBindViewHolder(holder: LeaderViewHolder, position: Int) { val model = list[position] Log.d("listelements","$model") // 显示初始排名,而非筛选后的列表位置 holder.binding.positionOfUser.text = "${model.rank} . " holder.binding.nameOfUser.text = model.name holder.binding.emailOfUser.text = model.email holder.binding.distanceCovered.text = model.distance }
步骤4:优化筛选逻辑(可选,提升性能)
避免每次筛选都创建新Adapter,给Adapter添加列表更新方法:
在LeaderboardAdapter中恢复注释的方法:
fun setLeaderBoardQuery(filteredList: ArrayList<User>){ this.list = filteredList notifyDataSetChanged() }
然后在Fragment中初始化一次Adapter并复用:
// Fragment中新增Adapter变量 private lateinit var leaderboardAdapter: LeaderboardAdapter fun getLeaderBoard(userList: ArrayList<User>) { // ...排序和设置排名的代码... leaderboardAdapter = LeaderboardAdapter(requireContext(), userList) binding.rvLeaderboard.adapter = leaderboardAdapter // ...其他代码... }
修改筛选方法:
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{ leaderboardAdapter.setLeaderBoardQuery(filteredLeaderBoardList) } }
完成以上修改后,搜索筛选出的用户会显示他们在初始排行榜中的真实排名,而非当前筛选列表的位置。
内容的提问来源于stack exchange,提问作者Jadu
相关产品推荐
相关产品推荐

