使用LinearLayoutManager在RecyclerView中滚动到顶部

95

我有一个包含RecyclerView的片段,其中使用LinearLayoutManager来布局CardView项。当点击浮动操作按钮时,应该将项目滚动到顶部。我已经尝试使用scrollToPositionscrollToPositionWithOffset方法,并将其与RecyclerViewLinearLayoutManager一起使用,如下所示。但这些尝试都没有效果。为什么会这样呢?请问有人可以帮帮我吗。

我在xml文件中直接将RecyclerView放置在SwipeRefreshView中。我在设置适配器后立即调用setFloatingActionButton方法。

 public void setFloatingActionButton(final View view) {
    float = (android.support.design.widget.FloatingActionButton) getActivity().findViewById(R.id.float);
    float.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
    mRecyclerView.smoothScrollToPosition(0);


            android.support.design.widget.Snackbar.make(view, "Scrolled to Top", android.support.design.widget.Snackbar.LENGTH_SHORT)
                    .setAction("Ok", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            LinearLayoutManager llm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
                            llm.scrollToPosition(0);

                        }
                    })
                    .setActionTextColor(getActivity().getResources().getColor(R.color.coloLink))
                    .show();
        }
    });
}

是的,我已经尝试过这个了。但它似乎跟 scrollToPosition 一样没有什么效果。 - SRBhagwat
当我将适配器设置到RecyclerView后立即调用scrollToPosition会有任何问题吗? - SRBhagwat
但是,当您第一次将适配器设置为“RecyclerView”时,默认情况下,列表会滚动到顶部。因此,您无需显式调用scrollToPosition。无论如何,尝试在一些延迟后运行它,通过使用一些延迟并进行检查。http://developer.android.com/reference/android/view/View.html#postDelayed(java.lang.Runnable, long) - Antrromet
1
现在我将 mlayoutmanager.scrollToPositionWithOffset(0,0); 放在 setFloatingActionButton 方法之外,它可以正常工作!!! - SRBhagwat
那么,当我点击浮动操作按钮时,有没有办法使用滚动到顶部? - SRBhagwat
显示剩余2条评论
9个回答

187

继续上面的评论,理想情况下,替换

mRecyclerView.smoothScrollToPosition(0);

在悬浮操作按钮的 onClick

mLayoutManager.scrollToPositionWithOffset(0, 0);

应该可以工作。你也可以删除SnackBar的代码,因为你根本不需要它。所以,总的来说,你上面的方法应该是这样的:

public void setFloatingActionButton(final View view) {
    float actionButton = (android.support.design.widget.FloatingActionButton) getActivity()
            .findViewById(R.id.float);
    actionButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView
                    .getLayoutManager();
            layoutManager.scrollToPositionWithOffset(0, 0);
        }
    });
}

如果您说上述方法不起作用,那么请测试一下onClick()是否被调用。尝试在其中添加一个日志消息,看看它是否被打印出来。


是的,我通过从其他片段中删除对此方法的调用来实现了它。我直接将fab创建放在onCreate()方法中。现在它完全正常工作。 - SRBhagwat
这个解决方案只在第一个片段中有效。如果我从两个片段都调用setFloatingActionActionButton,那么scrollToTop仅在第二个片段中起作用,而不在第一个片段中起作用。我正在从第一片段扩展第二片段。你能帮忙吗? - SRBhagwat
你为什么要在片段中调用它,而不是从活动中调用? - Antrromet
请问如何从主活动访问所有片段中的mRecyclerView,并设置scrollToPosition(0),以便在任何片段中单击FAB时,回收站视图滚动到顶部? - SRBhagwat
你能解释一下你的mRecyclerView是放在片段还是主活动中吗?如果可能,请发布片段和主活动的代码,这样我就可以了解你的应用程序的流程。 - Antrromet
显示剩余5条评论

19

使用方法smoothScrollToPosition()对我来说在最新的Android版本中有效。

layoutManager.smoothScrollToPosition(mRecyclerView, null, 0);

6

使用以下内容调用“scrollToPosition(0)”:

public void scrollToPosition(final int position) {
    if (mRecyclerView != null) {
        getHandler().post(new Runnable() {
            @Override
            public void run() {
                mRecyclerView.scrollToPosition(position);
                if (position == 0) {
                    LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
                    layoutManager.scrollToPositionWithOffset(0, 0);
                    mScrollView.fullScroll(View.FOCUS_UP);
                }
            }
        });
    }
}

mScrollView 是什么? - Wood
私有的 NestedScrollView mScrollView; - Lee Hounshell

4

如果您不想要平滑滚动,这将适用于任何 LayoutManager:

myRecyclerView.getLayoutManager().scrollToPosition(0);

2
以 Kotlin 为例
        // Scroll to the top of the list
        GlobalScope.launch(Dispatchers.Main) {
            delay(200)
            if (binding.rateList.size > 1) {
                //binding.recyclerView.smoothScrollToPosition(0)
                binding.recyclerView.layoutManager?.scrollToPosition(0)
            }

1
在我的情况下,要求是以相反的顺序填充视图,这使得布局显示滚动视图的底部视图。 layoutManager.smoothScrollToPosition(mRecyclerView, null, 'last_index') 没有真正帮助解决问题。
当我使回收站视图显示最后一个位置的子项时,我的问题得到了解决。

recyclerView.scrollToPosition(length-1)


0

有时用户使用NestedScrollView,对于NestedScrollView,我们可以使用以下代码。

 /*Scrolls NestedScrollView to the top of screen.*/
        viewBinding.scrollview.fullScroll(View.FOCUS_UP)

也许将来会有人受益于此。


0

以上的解决方案对我没有用,因为我的RecyclerView在NestedScrollView中。所以这个解决方案对我有用。

nestedScroll.smoothScrollTo(0,recycler.top)

1
在NestedScrollView中放置RecyclerView是个不好的主意。 - TimB
1
RecyclerView 嵌套在 NestedScrollView 中,列表项没有被回收但不断增加。应用程序明显存在滞后,最好单独使用 RecyclerView。 - Sunil

0
在 Kotlin 中,您可以为 RecyclerView 创建扩展:
fun RecyclerView.scrollToUp() = this.layoutManager?.scrollToPosition(0)

现在你可以在你的 RecyclerView 上调用这个函数:

yourRecyclerView.scrollToUp()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接