我正在寻找一种方法来滚动RecyclerView,以显示选中的项目在顶部。
在一个ListView中,我能够通过使用scrollTo(x,y)来做到这一点,并获得需要居中的元素的顶部。
喜欢的东西:
@Override
public void onItemClick(View v, int pos){
mylistView.scrollTo(0, v.getTop());
}
问题是RecyclerView在使用它的scrollTo方法时返回一个错误说
RecyclerView不支持滚动到绝对位置
我如何滚动一个RecyclerView把选定的项目放在视图的顶部?
简介
没有一个答案解释如何在顶部显示最后一项。因此,答案只适用于上面或下面仍然有足够的项来填充剩余的RecyclerView的项。例如,如果有59个元素,第56个元素被选中,它应该在顶部,如下图所示:
那么,让我们看看如何在下一段中实现它。
解决方案
我们可以使用linearLayoutManager来处理这些情况。scrollToPositionWithOffset(pos, 0)和额外的逻辑在适配器的RecyclerView -通过添加一个自定义边距下面的最后一项(如果最后一项是不可见的,那么这意味着有足够的空间填充RecyclerView)。自定义边距可以是根视图高度和项目高度之间的差值。因此,您的adaptor for RecyclerView将如下所示:
...
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
...
int bottomHeight = 0;
int itemHeight = holder.itemView.getMeasuredHeight();
// if it's the last item then add a bottom margin that is enough to bring it to the top
if (position == mDataSet.length - 1) {
bottomHeight = Math.max(0, mRootView.getMeasuredHeight() - itemHeight);
}
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)holder.itemView.getLayoutParams();
params.setMargins(0, 0, params.rightMargin, bottomHeight);
holder.itemView.setLayoutParams(params);
...
}
...
如果你想自动滚动而不显示滚动运动,那么你需要写以下代码:
mRecyclerView.getLayoutManager().scrollToPosition(position);
如果你想显示滚动运动,那么你需要添加以下代码。
步骤1:你需要声明SmoothScroller。
RecyclerView.SmoothScroller smoothScroller = new
LinearSmoothScroller(this.getApplicationContext()) {
@Override
protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};
=>步骤2:你需要添加这段代码任何事件,你想要执行滚动到特定的位置。
首先你需要设置目标位置为平滑滚动。
smoothScroller.setTargetPosition(position);
然后你需要将SmoothScroller设置为LayoutManager。
mRecyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
调速器也一样
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;
}
}
}