我正在寻找一种方法来滚动RecyclerView
以显示所选项目。
在ListView
中,我通过使用scrollTo(x,y)
并获取需要居中的元素的顶部来实现这一目标。
类似的东西:
@Override
public void onItemClick(View v, int pos){
mylistView.scrollTo(0, v.getTop());
}
问题是RecyclerView
在使用scrollTo
方法时会返回错误
RecyclerView不支持滚动到绝对位置
如何滚动RecyclerView
将所选项目置于视图顶部?
答案 0 :(得分:330)
如果您使用的是LinearLayoutManager
或交错的GridLayoutManager
,则每个方法都有一个scrollToPositionWithOffset方法,该方法同时从项目开始处获取项目开头的位置和偏移量RecyclerView
,看起来它可以完成你所需要的(将偏移设置为0应该与顶部对齐)。
例如:
//Scroll item 2 to 20 pixels from the top
linearLayoutManager.scrollToPositionWithOffset(2, 20);
答案 1 :(得分:82)
如果您正在寻找垂直LinearLayout Manager,您可以使用自定义LinearSmoothScroller
实现平滑滚动:
import android.content.Context;
import android.graphics.PointF;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSmoothScroller;
import android.support.v7.widget.RecyclerView;
public class SnappingLinearLayoutManager extends LinearLayoutManager {
public SnappingLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private class TopSnappedSmoothScroller extends LinearSmoothScroller {
public TopSnappedSmoothScroller(Context context) {
super(context);
}
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return SnappingLinearLayoutManager.this
.computeScrollVectorForPosition(targetPosition);
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
}
}
在循环视图中使用layoutmanager的一个实例,然后调用recyclerView.smoothScrollToPosition(pos);
将平滑滚动到所选位置到回收站视图的顶部
答案 2 :(得分:43)
//滚动项目pos
linearLayoutManager.scrollToPositionWithOffset(pos, 0);
答案 3 :(得分:17)
您只需致电recyclerview.scrollToPosition(position)
即可。没关系!
如果要在适配器中调用它,只需让适配器具有recyclerview实例或包含recyclerview的活动或片段,而不是在其中实现方法getRecyclerview()
。
我希望它可以帮到你。
答案 4 :(得分:11)
与速度调节器相同
public class SmoothScrollLinearLayoutManager extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 110f;
private Context mContext;
public SmoothScrollLinearLayoutManager(Context context,int orientation, boolean reverseLayout) {
super(context,orientation,reverseLayout);
mContext = context;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext()){
//This controls the direction in which smoothScroll looks for your view
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return new PointF(0, 1);
}
//This returns the milliseconds it takes to scroll one pixel.
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private class TopSnappedSmoothScroller extends LinearSmoothScroller {
public TopSnappedSmoothScroller(Context context) {
super(context);
}
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return SmoothScrollLinearLayoutManager.this
.computeScrollVectorForPosition(targetPosition);
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
}
}
答案 5 :(得分:6)
在点击按钮后刷新RecyclerView后我做了什么来恢复滚动位置:
if (linearLayoutManager != null) {
index = linearLayoutManager.findFirstVisibleItemPosition();
View v = linearLayoutManager.getChildAt(0);
top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop());
Log.d("TAG", "visible position " + " " + index);
}
else{
index = 0;
}
linearLayoutManager = new LinearLayoutManager(getApplicationContext());
linearLayoutManager.scrollToPositionWithOffset(index, top);
在创建linearLayoutManager对象之前从顶部获取第一个可见项的偏移量,并在实例化之后调用LinearLayoutManager对象的scrollToPositionWithOffset。
答案 6 :(得分:3)
在特定位置滚动
这对我很有帮助。
通过单击侦听器,您可以获得适配器中的位置
function PreviousProduct() {
$pages = ProductPage::get()->filter(array(
'ParentID' => $this->ParentID,
'Sort:LessThan' => $this->Sort
))->Sort('Sort')->reverse()->limit(1);
if ($pages->count()) {
return $pages->First();
}
$parent = $this->parent();
$parentSiblings = ProductRange::get()->filter(array(
'ParentID' => $parent->ParentID,
'Sort:LessThan' => $parent->Sort
))->Sort('Sort')->reverse();
foreach ($parentSiblings as $parentSibling) {
$pages = ProductPage::get()->filter(array(
'ParentID' => $parentSibling->ID
))->Sort('Sort')->reverse()->limit(1);
if ($pages->count()) {
return $pages->First();
}
}
return false;
}
答案 7 :(得分:3)
如果您的LayoutManager
是LinearLayoutManager
,则可以在其上使用scrollToPositionWithOffset(position,0);
,它将使您的商品成为列表中第一个可见的商品。否则,您可以直接在smoothScrollToPosition
上使用RecyclerView
。
我最终使用了以下代码。
RecyclerView.LayoutManager layoutManager = mainList.getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
// Scroll to item and make it the first visible item of the list.
((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(position, 0);
} else {
mainList.smoothScrollToPosition(position);
}
答案 8 :(得分:2)
在我的情况下,RecyclerView
有一个像这样的填充顶部
<android.support.v7.widget.RecyclerView
...
android:paddingTop="100dp"
android:clipToPadding="false"
/>
然后,要将项目滚动到顶部,我需要
recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, -yourRecyclerView.getPaddingTop());
答案 9 :(得分:1)
If you want to scroll automatic without show scroll motion then you need to write following code:
**=> mRecyclerView.getLayoutManager().scrollToPosition(position);**
If you want to display scroll motion then you need to add following code.
=>Step 1: You need to declare SmoothScroller.
RecyclerView.SmoothScroller smoothScroller = new
LinearSmoothScroller(this.getApplicationContext()) {
@Override
protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};
=>step 2: You need to add this code any event you want to perform scroll to specific position.
=>First you need to set target position to SmoothScroller.
**smoothScroller.setTargetPosition(position);**
=>Then you need to set SmoothScroller to LayoutManager.
**mRecyclerView.getLayoutManager().startSmoothScroll(smoothScroller);**
答案 10 :(得分:1)
我不知道为什么我找不到最佳答案,但这真的很简单。
recyclerView.smoothScrollToPosition(position);
没有错误
创建动画
答案 11 :(得分:1)
所有答案均未说明如何在顶部显示最后一个项目。因此,答案仅适用于在其上方或下方仍具有足够的项目来填充其余RecyclerView
的项目。例如,如果有59个元素并且选择了第56个元素,则它应位于顶部,如下图所示:
我们可以通过使用linearLayoutManager.scrollToPositionWithOffset(pos, 0)
和Adapter
的{{1}}中的附加逻辑来处理这些情况-通过在最后一项下方添加自定义边距(如果最后一项不可见,则意味着存在RecyclerView
中有足够的空间。自定义边距可以是根视图高度和项目高度之间的差异。因此,您的RecyclerView
的{{1}}如下所示:
Adapter
答案 12 :(得分:1)
请注意,如果 scrollToPosition
不起作用,请注意您的 RecyclerView 位于 NestedScrollView 内; refer to this post
答案 13 :(得分:0)
只需简单地调用此方法:
((LinearLayoutManager)RecyclerView.getLayoutManager()).scrollToPositionWithOffset(yourItemPosition,0);
而不是:
RecyclerView.scrollToPosition(yourItemPosition);
答案 14 :(得分:0)
我可以在此处添加的内容是如何使其与DiffUtil
和ListAdapter
一起工作
您可能会注意到,如果在recyclerView.scrollToPosition(pos)
之后直接调用直接,则无法调用(recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(pos, offset)
或adapter.submitList
。这是因为差异在后台线程中查找更改,然后异步通知适配器有关更改。在一个SO上,我看到了几个错误的答案以及不必要的延迟等等,以解决这个问题。
为正确处理这种情况,submitList
有一个回调,在应用更改后会调用该回调。
因此在这种情况下,正确的kotlin实现是:
//memorise target item here and a scroll offset if needed
adapter.submitList(items) {
val pos = /* here you may find a new position of the item or just use just a static position. It depends on your case */
recyclerView.scrollToPosition(pos)
}
//or
adapter.submitList(items) { recyclerView.smoothScrollToPosition(pos) }
//or etc
adapter.submitList(items) { (recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(pos, offset) }
答案 15 :(得分:-2)
我使用下面的代码将项目(thisView)平滑滚动到顶部 它也适用于具有不同高度视图的GridLayoutManager:
View firstView = mRecyclerView.getChildAt(0);
int toY = firstView.getTop();
int firstPosition = mRecyclerView.getChildAdapterPosition(firstView);
View thisView = mRecyclerView.getChildAt(thisPosition - firstPosition);
int fromY = thisView.getTop();
mRecyclerView.smoothScrollBy(0, fromY - toY);
似乎工作得很好,可以快速解决问题。