如何滚动到RecyclerView的底部? scrollToPosition不起作用

我想在加载活动后滚动到RecyclerView列表的底部。

GENERIC_MESSAGE_LIST = (ArrayList) intent.getExtras().getParcelableArrayList(ConversationsAdapter.EXTRA_MESSAGE); conversationView = (RecyclerView) findViewById(R.id.list_messages); conversationView.setHasFixedSize(true); conversationViewLayoutManager = new LinearLayoutManager(this); conversationView.setLayoutManager(conversationViewLayoutManager); conversationViewAdapter = new ConversationAdapter(GENERIC_MESSAGE_LIST, this); conversationView.setAdapter(conversationViewAdapter); 

conversationView.scrollTo(...)抛出一个关于在RecyclerView中不被支持的exception,而conversationView.scrollToPosition(...)似乎没有做任何事情。

上面的代码块后,我补充说

 conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size() + 1) 

这不起作用。 GENERIC_MESSAGE_LIST有30个元素。

只需要设置setStackFromEnd=true或者setReverseLayout=true这样LLM就会从结束项目布局。

这两者的区别在于setStackFromEnd将设置视图来显示最后一个元素,布局方向将保持不变。 (所以,在一个从左到右的水平Recycler视图中,最后一个元素将被显示,向左滚动将显示更早的元素)

setReverseLayout将更改适配器添加的元素的顺序。 布局将从最后一个元素开始,这将是LTR Recycler View中最左边的元素,然后向右滚动将显示更早的元素。

样品:

 final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); linearLayoutManager.setReverseLayout(true); _listView.setLayoutManager(linearLayoutManager); 

详细信息请参阅文档 。

我正在看这个post来find答案,但是…我想这个post上的每个人都面临着和我一样的情况:scrollToPosition()被完全忽略了,原因很明显。

我在用什么?

 recyclerView.scrollToPosition(items.size()); 

…什么工作

 recyclerView.scrollToPosition(items.size() - 1); 

我知道它迟到在这里回答,如果有人想知道下面的解决scheme

 conversationView.smoothScrollToPosition(conversationView.getAdapter().getItemCount() - 1); 

当你调用setAdapter时,它不会立即放置并在屏幕上定位项目(这需要一个布局传递),因此当您调用scrollToPosition()调用时,没有实际的元素可以滚动到。

相反,你应该注册一个ViewTreeObserver.OnGlobalLayoutListener (通过从conversationView.getViewTreeObserver()创build的ViewTreeObserver conversationView.getViewTreeObserver() ),它会延迟你的scrollToPosition()直到第一次布局传递为止:

 final ViewTreeObserver vto = conversationView.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size(); if (vto.isAlive()) { // Unregister the listener to only call scrollToPosition once vto.removeGlobalOnLayoutListener(this); // Use vto.removeOnGlobalLayoutListener(this) on API16+ devices as // removeGlobalOnLayoutListener is deprecated. // They do the same thing, just a rename so your choice. } } }); 

从回收站的任何位置滚动到底部

 edittext.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { rv_commentList.postDelayed(new Runnable() { @Override public void run() { rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1); } }, 1000); } }); 
 class MyLayoutManager extends LinearLayoutManager { public MyLayoutManager(Context context) { super(context, LinearLayoutManager.VERTICAL, false); } @Override public void smoothScrollToPosition(RecyclerView recyclerView, final RecyclerView.State state, final int position) { int fcvip = findFirstCompletelyVisibleItemPosition(); int lcvip = findLastCompletelyVisibleItemPosition(); if (position < fcvip || lcvip < position) { // scrolling to invisible position float fcviY = findViewByPosition(fcvip).getY(); float lcviY = findViewByPosition(lcvip).getY(); recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { int currentState = RecyclerView.SCROLL_STATE_IDLE; @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (currentState == RecyclerView.SCROLL_STATE_SETTLING && newState == RecyclerView.SCROLL_STATE_IDLE) { // recursive scrolling smoothScrollToPosition(recyclerView, state, position); } currentState = newState; } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { int fcvip = findFirstCompletelyVisibleItemPosition(); int lcvip = findLastCompletelyVisibleItemPosition(); if ((dy < 0 && fcvip == position) || (dy > 0 && lcvip == position)) { // stop scrolling recyclerView.setOnScrollListener(null); } } }); if (position < fcvip) { // scroll up recyclerView.smoothScrollBy(0, (int) (fcviY - lcviY)); } else { // scroll down recyclerView.smoothScrollBy(0, (int) (lcviY - fcviY)); } } else { // scrolling to visible position float fromY = findViewByPosition(fcvip).getY(); float targetY = findViewByPosition(position).getY(); recyclerView.smoothScrollBy(0, (int) (targetY - fromY)); } } } 

 MyLayoutManager layoutManager = new MyLayoutManager(context); recyclerView.setLayoutManager(layoutManager); RecyclerView.Adapter adapter = new YourAdapter(); recyclerView.setAdapter(adapter); recyclerView.smoothScrollToPosition(adapter.getItemCount() - 1); 

上面的代码工作,但它不光滑,不酷。

如果你有适配器与recyclerView连接,那么就这样做。

mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());

大鹏答案是一个很大的帮助。 我想添加一个小块:

 mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1); 

这对我来说非常好:

 AdapterChart adapterChart = new AdapterChart(getContext(),messageList); recyclerView.setAdapter(adapterChart); recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1); 

只有伊恩的答案是能够使我的RecyclerView滚动到指定的位置。 但是,当我使用scrollToPosition()时, RecyclerView无法滚动。 smoothScrollToPosition()工作,但是当列表很长的时候,最初的animation太慢了。 原因是听众没有被删除。 我使用下面的代码来删除当前的ViewTreeObserver ,它作为一个魅力。

  mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mRecyclerView.scrollToPosition(mPosition); mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); 
 recyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); layoutManager.setReverseLayout(true);// Scroll to bottom recyclerView.setLayoutManager(layoutManager);