使用 ItemTouchHelper 拖动项目时 RecyclerView 滚动到顶部
Posted
技术标签:
【中文标题】使用 ItemTouchHelper 拖动项目时 RecyclerView 滚动到顶部【英文标题】:RecyclerView scrolls to top when dragging item with ItemTouchHelper 【发布时间】:2021-01-15 03:49:39 【问题描述】:我有一个奇怪的错误,每当我开始在其中拖动项目时,我的RecyclerView
就会滚动回顶部位置。如果有任何区别,它就在ViewPager
里面。您可以在附加的 .gif 中看到行为。
编辑:
似乎RecyclerView
视图在调用notifyItemMoved
时滚动到顶部,并且它滚动的幅度与第一个视图至少部分显示在屏幕上的程度相同。
查看
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/accounts_recycler_view"
android:layout_
android:layout_
android:scrollbarStyle="outsideOverlay"
android:scrollbars="none"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/view_account_list_item" />
适配器
class AccountListAdapter(
private val onAccountClickListener: OnAccountClickListener) :
ListAdapter<Account, AccountListAdapter.ViewHolder>(
AccountDiffCallback()
)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder
val inflater = LayoutInflater.from(parent.context)
return ViewHolder(
inflater.inflate(
R.layout.view_account_list_item,
parent,
false
)
)
override fun getItemId(position: Int): Long
return getItem(position).accountId.toLong()
override fun onBindViewHolder(holder: ViewHolder, position: Int)
holder.bind(getItem(position), onAccountClickListener)
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), OnItemDragged
fun bind(account: Account, onAccountClickListener: OnAccountClickListener)
itemView.account_name.text = account.name
itemView.setOnClickListener
onAccountClickListener.onAccountClick(account)
override fun onItemSelected()
itemView.setBackgroundColor(
ContextCompat.getColor(
itemView.context,
R.color.background_contrast
)
)
override fun onItemClear()
itemView.setBackgroundColor(
ContextCompat.getColor(
itemView.context,
R.color.background
)
)
class AccountDiffCallback : DiffUtil.ItemCallback<Account>()
override fun areItemsTheSame(oldItem: Account, newItem: Account): Boolean
return oldItem.accountId == newItem.accountId
override fun areContentsTheSame(oldItem: Account, newItem: Account): Boolean
return (oldItem.balance == newItem.balance
&& oldItem.annualReturn == newItem.annualReturn
&& oldItem.name == newItem.name)
interface OnAccountClickListener
fun onAccountClick(account: Account)
interface OnItemDragged
fun onItemSelected()
fun onItemClear()
ItemTouchHelper
private fun setupListAdapter()
accountListAdapter = AccountListAdapter(this)
accountListAdapter.setHasStableIds(true)
accounts_recycler_view.adapter = accountListAdapter
accounts_recycler_view.addItemDecoration(
DividerItemDecoration(
requireContext(),
DividerItemDecoration.VERTICAL
)
)
val accountTouchHelper = ItemTouchHelper(
object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
0
)
override fun onSelectedChanged(
viewHolder: RecyclerView.ViewHolder?,
actionState: Int
)
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG)
val accountViewHolder = viewHolder as AccountListAdapter.ViewHolder
accountViewHolder.onItemSelected()
super.onSelectedChanged(viewHolder, actionState)
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
)
val accountViewHolder = viewHolder as AccountListAdapter.ViewHolder
accountViewHolder.onItemClear()
super.clearView(recyclerView, viewHolder)
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean
val fromPos: Int = viewHolder.adapterPosition
val toPos: Int = target.adapterPosition
Collections.swap(_accountList, fromPos, toPos)
accountListAdapter.notifyItemMoved(fromPos, toPos)
return true
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int)
)
accountTouchHelper.attachToRecyclerView(accounts_recycler_view)
【问题讨论】:
【参考方案1】:所以问题是我的 Recyclerview
在 ViewPager
里面,它在 ConstraintLayout
里面。视图寻呼机受到垂直限制,高度设置为 0dp,但宽度设置为 match_parent
。我所需要的只是将其水平约束,宽度设置为 0dp,setHasFixedSize = true
到 RecyclerView
当为适配器调用notifyItemMoved
时,如果RecyclerView
是灵活的,则重绘所有项目,默认情况下聚焦第一个项目。
【讨论】:
以上是关于使用 ItemTouchHelper 拖动项目时 RecyclerView 滚动到顶部的主要内容,如果未能解决你的问题,请参考以下文章
RecyclerView ItemTouchHelper.Callback:拖动交换条件
Android开发 RecyclerView实现拖动与滑动ItemTouchHelper
Android开发 RecyclerView实现拖动与滑动ItemTouchHelper
RecyclerView借助ItemTouchHelper实现拖动和滑动删除功能