如何滚动到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);