OnBindViewHolder 更新自动滚动到顶部
OnBindViewHolder on update autoScroll to top
在适配器 submitList 到 DiffUtil 之后,调用 onBindViewHolder 并且由于某种原因它总是将列表滚动到顶部。
我尝试了 SO 中关于在 recyclerview 更新列表上自动滚动的每一个答案,但无法解决问题。
即
RecyclerView scrolls to top on notifyDataSetChanged in chat screen
android notifyItemRangeInserted disable autoscroll
等
这是我的适配器:
init {
setHasStableIds(true)
}
private val currentDiffer = AsyncListDiffer<Item>(this, MyDiffUtil())
...
override fun setHasStableIds(hasStableIds: Boolean) {
super.setHasStableIds(true)
}
override fun getItemCount(): Int {
return currentDiffer.currentList.size
}
override fun getItemId(position: Int): Long = currentDiffer.currentList[position].name.hashCode().toLong()
override fun getItemViewType(position: Int) = position
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
}
override fun onBindViewHolder(holder: CurrentListViewHolder, position: Int) {
holder.bindView(position, activity, currentDiffer.currentList[position], onCurrencyListener)
}
override fun onViewRecycled(holder: CurrentListViewHolder) {
holder.unbindView()
super.onViewRecycled(holder)
}
fun setData(list: LinkedList<Item>) {
val newList: LinkedList<Item> = LinkedList()
newList.addAll(list)
currentDiffer.submitList(newList.toList())
}
因此,在每次新提交列表之后,无论当前位置是什么,都会调用 onBindViewHolder 并且在它执行任何操作之前,列表会滚动到 0 位置,就像调用 scrollToPosition 一样。
编辑:
private fun setView() {
currentListAdapter = CurrentListAdapter()
with(currenciesRv) {
layoutManager = LinearLayoutManager(context)
adapter = currentListAdapter
}
布局:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listRv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
项目:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/itemLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/itemIvFlag"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="30dp"
android:layout_marginStart="15dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/itemIvFlag"
android:orientation="vertical"
android:layout_centerVertical="true"
android:layout_marginTop="10dp">
<TextView
android:id="@+id/itemTvISO"
android:layout_marginStart="10dp"
android:textStyle="bold"
tools:text="@string/dummy_number"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/itemTvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:textSize="14sp"
tools:text="@string/dummy_number"/>
</LinearLayout>
<EditText
android:id="@+id/itemEtAmount"
android:layout_alignParentEnd="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="15dp"
tools:text="@string/dummy_number"
android:inputType="numberDecimal"
android:enabled="false"
android:textColor="@drawable/et_disabled_color"
android:imeOptions="actionDone"
android:maxLines="1"
android:singleLine="true"/>
</RelativeLayout>
Post 覆盖 DiffUtil 比较提交列表的方法。我遇到了类似的问题(我的问题是 RecycleView 一直关注显示加载视图的 list_item_network_state)。从你的 post "every few seconds the list is refreshed from the server and if the list is scrolled down, onBindViewHolder scrolls it back to 0" 下的评论来看,当数据正在更新并且它包含相同的项目时,你想关注旧列表中的焦点元素吗?
很难为您的问题找到解决方案(信息不足)我认为问题不在您的适配器上。
另外建议使用 ListAdapter
它本身有 DiffUtil.ItemCallback。
更新
因此,如果您在 onBIndViewHolder 中没有任何内容,它仍然会滚动到顶部,这意味着问题不存在。问题在于提交新列表(如 DiffUtil "it used to calculate updates for a RecyclerView Adapter.")。在比较过程中,它决定 delete/update/add 项目的位置。可能存在问题(这是我对您提供的信息的假设,如果可能的话,向您的问题添加更多代码)。将方法检查为 areItemsTheSame()(例如,它必须比较项目的 id)并在调用 areContentsTheSame() 之后检查已更改的内容。
问题出在我的 DiffUtil 上。我鲁莽又草率,wrong/basically 在 areItemsTheSame
和 areContentsTheSame
上有相同的值,所以 diffUtil 认为它们之间没有区别,这意味着每个新内容都与新项目相同。
在适配器 submitList 到 DiffUtil 之后,调用 onBindViewHolder 并且由于某种原因它总是将列表滚动到顶部。
我尝试了 SO 中关于在 recyclerview 更新列表上自动滚动的每一个答案,但无法解决问题。
即
RecyclerView scrolls to top on notifyDataSetChanged in chat screen
android notifyItemRangeInserted disable autoscroll
等
这是我的适配器:
init {
setHasStableIds(true)
}
private val currentDiffer = AsyncListDiffer<Item>(this, MyDiffUtil())
...
override fun setHasStableIds(hasStableIds: Boolean) {
super.setHasStableIds(true)
}
override fun getItemCount(): Int {
return currentDiffer.currentList.size
}
override fun getItemId(position: Int): Long = currentDiffer.currentList[position].name.hashCode().toLong()
override fun getItemViewType(position: Int) = position
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
}
override fun onBindViewHolder(holder: CurrentListViewHolder, position: Int) {
holder.bindView(position, activity, currentDiffer.currentList[position], onCurrencyListener)
}
override fun onViewRecycled(holder: CurrentListViewHolder) {
holder.unbindView()
super.onViewRecycled(holder)
}
fun setData(list: LinkedList<Item>) {
val newList: LinkedList<Item> = LinkedList()
newList.addAll(list)
currentDiffer.submitList(newList.toList())
}
因此,在每次新提交列表之后,无论当前位置是什么,都会调用 onBindViewHolder 并且在它执行任何操作之前,列表会滚动到 0 位置,就像调用 scrollToPosition 一样。
编辑:
private fun setView() {
currentListAdapter = CurrentListAdapter()
with(currenciesRv) {
layoutManager = LinearLayoutManager(context)
adapter = currentListAdapter
}
布局:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listRv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
项目:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/itemLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/itemIvFlag"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginTop="30dp"
android:layout_marginStart="15dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/itemIvFlag"
android:orientation="vertical"
android:layout_centerVertical="true"
android:layout_marginTop="10dp">
<TextView
android:id="@+id/itemTvISO"
android:layout_marginStart="10dp"
android:textStyle="bold"
tools:text="@string/dummy_number"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/itemTvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:textSize="14sp"
tools:text="@string/dummy_number"/>
</LinearLayout>
<EditText
android:id="@+id/itemEtAmount"
android:layout_alignParentEnd="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginEnd="15dp"
tools:text="@string/dummy_number"
android:inputType="numberDecimal"
android:enabled="false"
android:textColor="@drawable/et_disabled_color"
android:imeOptions="actionDone"
android:maxLines="1"
android:singleLine="true"/>
</RelativeLayout>
Post 覆盖 DiffUtil 比较提交列表的方法。我遇到了类似的问题(我的问题是 RecycleView 一直关注显示加载视图的 list_item_network_state)。从你的 post "every few seconds the list is refreshed from the server and if the list is scrolled down, onBindViewHolder scrolls it back to 0" 下的评论来看,当数据正在更新并且它包含相同的项目时,你想关注旧列表中的焦点元素吗?
很难为您的问题找到解决方案(信息不足)我认为问题不在您的适配器上。
另外建议使用 ListAdapter
它本身有 DiffUtil.ItemCallback。
更新 因此,如果您在 onBIndViewHolder 中没有任何内容,它仍然会滚动到顶部,这意味着问题不存在。问题在于提交新列表(如 DiffUtil "it used to calculate updates for a RecyclerView Adapter.")。在比较过程中,它决定 delete/update/add 项目的位置。可能存在问题(这是我对您提供的信息的假设,如果可能的话,向您的问题添加更多代码)。将方法检查为 areItemsTheSame()(例如,它必须比较项目的 id)并在调用 areContentsTheSame() 之后检查已更改的内容。
问题出在我的 DiffUtil 上。我鲁莽又草率,wrong/basically 在 areItemsTheSame
和 areContentsTheSame
上有相同的值,所以 diffUtil 认为它们之间没有区别,这意味着每个新内容都与新项目相同。