我正在寻找一种方法来滚动RecyclerView,以显示选中的项目在顶部。

在一个ListView中,我能够通过使用scrollTo(x,y)来做到这一点,并获得需要居中的元素的顶部。

喜欢的东西:

@Override
public void onItemClick(View v, int pos){
    mylistView.scrollTo(0, v.getTop());
}

问题是RecyclerView在使用它的scrollTo方法时返回一个错误说

RecyclerView不支持滚动到绝对位置

我如何滚动一个RecyclerView把选定的项目放在视图的顶部?


当前回答

我所做的恢复滚动位置后刷新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。

其他回答

我可以在这里添加的是如何使它与DiffUtil和ListAdapter一起工作

你可能会注意到调用recyclerView. scrolltopposition (pos)或(recyclerView. scrolltopposition)。layoutManager作为LinearLayoutManager)。如果在adapter.submitList后直接调用scrollToPositionWithOffset(pos, offset)将不起作用。这是因为differ在后台线程中查找更改,然后异步地将更改通知适配器。在一个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) }

如果你寻找垂直线性布局管理器,你可以实现平滑滚动使用自定义线性平滑scroller:

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;
        }
    }
}

在循环视图中使用布局管理器的实例,然后调用recyclerview . smoothscrolltopposition (pos);将平滑滚动到选定的位置到回收视图的顶部

调速器也一样

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;
    }
}
}

特定位置滚动 这对我帮助很大。 通过单击listener,您可以获得适配器中的位置

layoutmanager.scrollToPosition(int position);

在我的情况下,我的RecyclerView有一个填充顶部像这样

<android.support.v7.widget.RecyclerView
     ...
     android:paddingTop="100dp"
     android:clipToPadding="false"
/>

然后滚动一个项目到顶部,我需要

recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, -yourRecyclerView.getPaddingTop());