作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 diff util 来提高我的 recyclerview 的性能,而不是调用 notifyDataSetChanged()。 recyclerview 有一个带有一些芯片的标题,可以通过 aplhabetical 顺序重新排序列表,最高分数等
当我单击标题中的筹码时,列表会对其重新排序,从而影响我的位置。例如,如果我按最高分数排序并且分数 100% 是位置 1(在标题之后),我单击芯片以反向重新排序。分数 100% 现在将位于列表的底部,而 0% 将位于顶部。但现在我必须一直滚动到顶部才能再次看到标题芯片。我希望列表重新排序,但我不希望我在屏幕上的位置改变。
这是我的适配器代码:
class DigitalTestsResultsAdapter(
private val interaction: Interaction? = null,
private val dateUtil: DateUtil,
private val theme: ThemeModel?,
private val username: String?
) : ListAdapter<ResultResponseModel, RecyclerView.ViewHolder>(ResultsDiffCallBack()) {
private val itemViewTypeHeader: Int = 0
private val itemViewTypeItem: Int = 1
private var filteredList = emptyList<ResultResponseModel>()
private val adapterScope = CoroutineScope(Dispatchers.Default)
class ResultsDiffCallBack : DiffUtil.ItemCallback<ResultResponseModel>() {
override fun areItemsTheSame(
oldItem: ResultResponseModel,
newItem: ResultResponseModel
): Boolean {
return oldItem.certificateUrl == newItem.certificateUrl
}
@SuppressLint("DiffUtilEquals")
override fun areContentsTheSame(
oldItem: ResultResponseModel,
newItem: ResultResponseModel
): Boolean {
return oldItem == newItem
}
}
fun filterList(list: List<ResultResponseModel>, type: String) {
adapterScope.launch {
when (type) {
"courseName" -> {
filteredList = list.sortedBy { it.courseName }
}
"isCpd" -> {
filteredList = list.sortedBy { it.courseName }.sortedByDescending { it.isCPD }
}
"organisationName" -> {
filteredList = list.sortedBy { it.organisationName }
}
"roleName" -> {
filteredList = list.sortedBy { it.roleName }
}
"score" -> {
filteredList = list.sortedByDescending { it.score }
}
"submitTime" -> {
filteredList = list.sortedByDescending { it.submitTime }
}
}
withContext(Dispatchers.Main) {
submitList(filteredList)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
itemViewTypeHeader -> {
DigitalTestsResultsHeaderViewHolder(
RvDigitalTestResultsHeaderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
itemViewTypeItem -> {
DigitalTestsResultsViewHolder(
RvDigitalTestsResultsBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
),
interaction = interaction
)
}
else -> throw ClassCastException("Unknown viewType $viewType")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is DigitalTestsResultsHeaderViewHolder -> {
holder.bind()
}
is DigitalTestsResultsViewHolder -> {
holder.bind(currentList[position])
}
}
}
override fun getItemViewType(position: Int): Int {
return if (position == 0) {
itemViewTypeHeader
} else {
itemViewTypeItem
}
}
override fun getItemCount(): Int {
return if (!currentList.isNullOrEmpty()) {
currentList.size
} else 0
}
inner class DigitalTestsResultsHeaderViewHolder
constructor(
private val binding: RvDigitalTestResultsHeaderBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind() {
with(binding) {
with(theme) {
userName.text = itemView.context.getString(R.string.hi_username, username)
userName.setTextColourHex(this?.textModel?.primaryColor)
chipCv.setCardBackgroundColourHex(this?.interfaceModel?.secondaryColor)
testsChipGroup.setOnCheckedChangeListener { _, checkedId ->
when (checkedId) {
R.id.chipCertified -> {
chipCertified.isChecked = true
filterList(currentList, "isCpd")
}
R.id.chipCourse -> {
chipCourse.isChecked = true
filterList(currentList, "courseName")
}
R.id.chipHighestScore -> {
chipHighestScore.isChecked = true
filterList(currentList, "score")
}
R.id.chipRecent -> {
chipRecent.isChecked = true
filterList(currentList, "submitTime")
}
R.id.chipRole -> {
chipRole.isChecked = true
filterList(currentList, "roleName")
}
R.id.chipSchoolName -> {
chipSchoolName.isChecked = true
filterList(currentList, "organisationName")
}
else -> {
}
}
}
}
}
}
}
inner class DigitalTestsResultsViewHolder
constructor(
private val binding: RvDigitalTestsResultsBinding,
private val interaction: Interaction?
) : RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(item: ResultResponseModel?) {
with(binding) {
with(theme) {
viewCertificateBtn.setOnClickListener {
interaction?.onItemSelected("certificateBtn", absoluteAdapterPosition, item)
}
retakeTestBtn.setOnClickListener {
interaction?.onItemSelected("retakeTestBtn", absoluteAdapterPosition, item)
}
resultsProgressBar.progress = item?.score?.toFloat() ?: 0f
if (isValidHex(item?.roleColour)) {
resultsProgressBar.circleProgressColor = Color.parseColor(item?.roleColour)
resultsProgressBar.pointerColor = Color.parseColor(item?.roleColour)
}
score.text = item?.score.toString() + "%"
title.text = item?.courseName
date.text = dateUtil.formatStringDateToDDMMYYYY(item?.submitTime)
role.text = item?.roleName
schoolName.text = item?.organisationName
title.setTextColourHex(this?.textModel?.primaryColor)
retakeTestBtn.setTextColourHex(this?.textModel?.primaryColor)
mainCv.setCardBackgroundColourHex(this?.interfaceModel?.secondaryColor)
roleCv.setCardBackgroundColourHex(item?.roleColour)
// Check if course is CPD and display CPD icon
if (item?.isCPD == true) cpdLogo.visibility =
View.VISIBLE else cpdLogo.visibility = View.INVISIBLE
}
}
}
}
interface Interaction {
fun onItemSelected(
tag: String,
position: Int,
result: ResultResponseModel?
)
}
}
最佳答案
使用 registerAdapterDataObserver 注册适配器以观察以在数据更改时通知您adapter.registerAdapterDataObserver()
当数据更改时,将 recyclerView 滚动到第一项位置
使用 recyclerview.scrollToPosition(position)
也可以看看:
Recycler view scroll to specific position
和 Diffutil in recycleview, making it autoscroll if a new item is added
关于android - 当列表按降序排序时,DiffUtil 正在改变我的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70379617/
我是一名优秀的程序员,十分优秀!