简体   繁体   English

使用 ItemTouchHelper 拖动项目时 RecyclerView 滚动到顶部

[英]RecyclerView scrolls to top when dragging item with ItemTouchHelper

I have this weird bug where my RecyclerView scrolls back to top position whenever I start dragging an item in it.我有一个奇怪的错误,每当我开始在其中拖动项目时,我的RecyclerView滚动回顶部位置。 It's inside ViewPager if that has any difference.如果有任何区别,它在ViewPager You can see the behavior in .gif attached.您可以在 .gif 附件中看到该行为。

EDIT:编辑:

It seems that RecyclerView view scrolls to top when notifyItemMoved is called and it scrolls just as much for the first view to be at least partially displayed on screen.似乎RecyclerView视图在notifyItemMoved时滚动到顶部,并且它滚动到第一个视图至少部分显示在屏幕上。

在此处输入图片说明

View看法

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/accounts_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbarStyle="outsideOverlay"
    android:scrollbars="none"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
    tools:listitem="@layout/view_account_list_item" />

Adapter适配器

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

}

So the issues was that my Recyclerview was inside ViewPager which was inside a ConstraintLayout .所以问题是我的RecyclerviewViewPager里面,它在ConstraintLayout里面。 View pager was constrained vertically with height set to 0dp but width was set to match_parent .视图寻呼机被垂直约束,高度设置为 0dp 但宽度设置为match_parent All I needed was to constrain it horizontally with width set to 0dp and setHasFixedSize = true to RecyclerView我所需要的只是将其水平约束,宽度设置为 0dp 并将setHasFixedSize = trueRecyclerView

When calling notifyItemMoved for adapter, if RecyclerView is flexible, all items are redrawn and by default it focuses on the first item.当为适配器调用notifyItemMoved ,如果RecyclerView灵活,则所有项目都会重绘,默认情况下它会关注第一项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 更改列表项布局时 RecyclerView 滚动到顶部 - When changing list item layout RecyclerView scrolls to top 拖动时如何在使用 ItemTouchHelper 时取消 RecyclerView 中项目的拖动? - How to cancel dragging of items in RecyclerView when using ItemTouchHelper, as you drag? RecyclerView通过itemTouchHelper拖放,拖动时快速拖动 - RecyclerView drag & drop via itemTouchHelper bahaving strange when dragging fast RecyclerView ItemTouchHelper.Callback:拖动交换条件 - RecyclerView ItemTouchHelper.Callback: Dragging swap condition 在重写getItemViewType()之后,为什么带有ItemTouchHelper的RecyclerView在只有一个项目之后停止拖动? - Why does my RecyclerView with ItemTouchHelper stop dragging after only one item, after overriding getItemViewType()? 使用 ItemTouchHelper 从 RecyclerView 中删除项目时引发 UnsupportedOperationException - UnsupportedOperationException is thrown when removing item from RecyclerView using ItemTouchHelper 在顶部插入时,RecyclerView GridLayoutManager向下滚动 - RecyclerView GridLayoutManager scrolls down when inserting at top 单击项目 Android 时 RecyclerView 滚动 - RecyclerView scrolls when click on item Android 展开项目时,RecyclerView向下滚动 - RecyclerView scrolls down when expanding item android 限制项目在范围内拖动 itemtouchhelper - android limit item dragging in a range itemtouchhelper
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM