Java 如何滚动到 RecyclerView 的底部?scrollToPosition 不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26580723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to scroll to the bottom of a RecyclerView? scrollToPosition doesn't work
提问by waylaidwanderer
I'd like to scroll to the bottom of the RecyclerView list after loading the activity.
我想在加载活动后滚动到 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(...)
throws an exception about being not supported in RecyclerView, and conversationView.scrollToPosition(...)
doesn't seem to do anything.
conversationView.scrollTo(...)
引发关于 RecyclerView 不支持的异常,并且conversationView.scrollToPosition(...)
似乎没有做任何事情。
After the above block of code, I added
在上面的代码块之后,我添加了
conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size() + 1)
which doesn't work. There are 30 elements in GENERIC_MESSAGE_LIST
.
这不起作用。中有 30 个元素GENERIC_MESSAGE_LIST
。
采纳答案by yigit
Just set setStackFromEnd=true
or setReverseLayout=true
so that LLM will layout items from end.
只需设置setStackFromEnd=true
或setReverseLayout=true
使LLM将布局从最终产品。
The difference between these two is that setStackFromEnd
will set the view to show the last element, the layout direction will remain the same. (So, in an left-to-right horizontal Recycler View, the last element will be shown and scrolling to the left will show the earlier elements)
这两者的区别在于setStackFromEnd
将视图设置为显示最后一个元素,布局方向将保持不变。(因此,在从左到右的水平 Recycler View 中,将显示最后一个元素,向左滚动将显示较早的元素)
Whereas setReverseLayout
will change the order of the elements added by the Adapter. The layout will start from the last element, which will be the left-most in an LTR Recycler View and then, scrolling to the right will show the earlier elements.
而setReverseLayout
将更改由适配器添加的元素的顺序。布局将从最后一个元素开始,这将是 LTR 回收器视图中最左侧的元素,然后向右滚动将显示较早的元素。
Sample:
样本:
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setReverseLayout(true);
_listView.setLayoutManager(linearLayoutManager);
See documentationfor details.
有关详细信息,请参阅文档。
回答by ianhanniballake
When you call setAdapter
, that does not immediately lay out and position items on the screen (that takes a single layout pass) hence your scrollToPosition()
call has no actual elements to scroll to when you call it.
当您调用setAdapter
时,它不会立即在屏幕上布置和定位项目(需要一次布局传递),因此scrollToPosition()
当您调用它时,您的调用没有可滚动到的实际元素。
Instead, you should register a ViewTreeObserver.OnGlobalLayoutListener(via addOnGlobalLayoutListner()from a ViewTreeObserver
created by conversationView.getViewTreeObserver()
) which delays your scrollToPosition()
until after the first layout pass:
相反,您应该注册一个ViewTreeObserver.OnGlobalLayoutListener(通过来自created by 的addOnGlobalLayoutListner()),它会延迟您直到第一次布局传递之后:ViewTreeObserver
conversationView.getViewTreeObserver()
scrollToPosition()
conversationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size();
// Unregister the listener to only call scrollToPosition once
conversationView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// Use vto.removeOnGlobalLayoutListener(this) on API16+ devices as
// removeGlobalOnLayoutListener is deprecated.
// They do the same thing, just a rename so your choice.
}
});
回答by Yuki Yoshida
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));
}
}
}
and
和
MyLayoutManager layoutManager = new MyLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);
RecyclerView.Adapter adapter = new YourAdapter();
recyclerView.setAdapter(adapter);
recyclerView.smoothScrollToPosition(adapter.getItemCount() - 1);
above code works, but it's not smooth and not cool.
上面的代码有效,但不流畅也不酷。
回答by Roc Boronat
I was looking at this post to find the answer but... I think everyone on this post was facing the same scenario as me: scrollToPosition()
was fully ignored, for an evident reason.
我正在查看这篇文章以寻找答案,但是......我认为这篇文章中的每个人都面临着与我相同的情况:scrollToPosition()
出于明显的原因,被完全忽略了。
What I was using?
我用的是什么?
recyclerView.scrollToPosition(items.size());
... what WORKED?
...什么工作?
recyclerView.scrollToPosition(items.size() - 1);
回答by Muhammad Umair Shafique
To scrolldown from any position in the recyclerview to bottom
从回收站视图中的任何位置向下滚动到底部
edittext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
rv.postDelayed(new Runnable() {
@Override
public void run() {
rv.scrollToPosition(rv.getAdapter().getItemCount() - 1);
}
}, 1000);
}
});
回答by WritingForAnroid
I know its late to answer here, still if anybody want to know solution is below
我知道在这里回答晚了,如果有人想知道下面的解决方案
conversationView.smoothScrollToPosition(conversationView.getAdapter().getItemCount() - 1);
回答by Anky An
Only Ian's answer was able to make my RecyclerView
scroll to a specified position. However, The RecyclerView
was not able to scroll afterwards when I used scrollToPosition()
. smoothScrollToPosition()
worked but the initial animation made it too slow when the list was long.
The reason was the listener was not removed. I used the code below to remove the current ViewTreeObserver
and it worked as a charm.
只有 Ian 的回答能够使我的RecyclerView
滚动到指定位置。但是,RecyclerView
当我使用scrollToPosition()
. smoothScrollToPosition()
工作,但当列表很长时,初始动画使它变得太慢。原因是监听器没有被移除。我使用下面的代码来删除电流ViewTreeObserver
,它起到了很好的作用。
mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mRecyclerView.scrollToPosition(mPosition);
mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
回答by Wasim Amin
IF you have adapter attached with recyclerView then just do this.
如果您的适配器与 recyclerView 相连,则只需执行此操作。
mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());
mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());
回答by abedfar
Roc answer is a great help. I would like to add a small block to it:
Roc 的回答很有帮助。我想给它添加一个小块:
mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
回答by amaresh hiremani
This works perfectly fine for me:
这对我来说非常好:
AdapterChart adapterChart = new AdapterChart(getContext(),messageList);
recyclerView.setAdapter(adapterChart);
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1);