RecyclerView - 如何在某个位置平滑滚动到项目顶部?

问题描述 投票:86回答:8

在RecyclerView上,我可以使用以下命令突然滚动到所选项目的顶部:

((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);

但是,这突然将项目移动到顶部位置。我想顺利地移动到项目的顶部。

我也尝试过:

recyclerView.smoothScrollToPosition(position);

但它不能很好地工作,因为它不会将项目移动到选定的顶部位置。它只是滚动列表,直到位置上的项目可见。

android scroll position android-recyclerview smooth
8个回答
166
投票

RecyclerView被设计为可扩展的,因此不需要为了执行滚动而将LayoutManager(如droidev suggested)子类化。

相反,只需使用首选项SmoothScroller创建一个SNAP_TO_START

RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
  @Override protected int getVerticalSnapPreference() {
    return LinearSmoothScroller.SNAP_TO_START;
  }
};

现在,您可以设置要滚动到的位置:

smoothScroller.setTargetPosition(position);

并将SmoothScroller传递给LayoutManager:

layoutManager.startSmoothScroll(smoothScroller);

106
投票

为此,您必须创建自定义LayoutManager

public class LinearLayoutManagerWithSmoothScroller extends LinearLayoutManager {

    public LinearLayoutManagerWithSmoothScroller(Context context) {
        super(context, VERTICAL, false);
    }

    public LinearLayoutManagerWithSmoothScroller(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 LinearLayoutManagerWithSmoothScroller.this
                    .computeScrollVectorForPosition(targetPosition);
        }

        @Override
        protected int getVerticalSnapPreference() {
            return SNAP_TO_START;
        }
    }
}

将它用于RecyclerView并调用smoothScrollToPosition。

例如:

 recyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(context));
 recyclerView.smoothScrollToPosition(position);

这将滚动到指定位置的RecyclerView项目的顶部。

希望这可以帮助。


8
投票

我们可以这样试试

    recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(), recyclerView.getAdapter().getItemCount());

6
投票

这是我在Kotlin写的一个扩展函数,直接在RecyclerView上调用(基于@Paul Woitaschek答案):

fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
    val smoothScroller = object: LinearSmoothScroller(this.context) {
        override fun getVerticalSnapPreference(): Int {
            return snapMode
        }

        override fun getHorizontalSnapPreference(): Int {
            return snapMode
        }
    }
    smoothScroller.targetPosition = position
    layoutManager?.startSmoothScroll(smoothScroller)
}

像这样使用它:

myRecyclerView.smoothSnapToPosition(itemPosition)

3
投票

我发现滚动RecyclerView最简单的方法如下:

// Define the Index we wish to scroll to.
final int lIndex = 0;
// Assign the RecyclerView's LayoutManager.
this.getRecyclerView().setLayoutManager(this.getLinearLayoutManager());
// Scroll the RecyclerView to the Index.
this.getLinearLayoutManager().smoothScrollToPosition(this.getRecyclerView(), new RecyclerView.State(), lIndex);

2
投票

覆盖LinearSmoothScroller中的calculateDyToMakeVisible / calculateDxToMakeVisible函数以实现偏移Y / X位置

override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
    return super.calculateDyToMakeVisible(view, snapPreference) - ConvertUtils.dp2px(10f)
}

1
投票

我喜欢这样:

recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, new RecyclerView.State(), 5);

0
投票

可能@droidev方法是正确的,但我只想发布一些不同的东西,它基本上做同样的工作,不需要扩展LayoutManager。

这里有一个注意事项 - 如果你的项目(你要在列表顶部滚动的项目)在屏幕上可见,你只需要自动滚动到顶部就可以了。当列表中的最后一项具有某些操作时会很有用,这会在同一列表中添加新项目,并且您希望将用户集中在新添加的项目上:

int recyclerViewTop = recyclerView.getTop();
int positionTop = recyclerView.findViewHolderForAdapterPosition(positionToScroll) != null ? recyclerView.findViewHolderForAdapterPosition(positionToScroll).itemView.getTop() : 200;
final int calcOffset = positionTop - recyclerViewTop; 
//then the actual scroll is gonna happen with (x offset = 0) and (y offset = calcOffset)
recyclerView.scrollBy(0, offset);

这个想法很简单:1。我们需要获得recyclerview元素的顶部坐标; 2.我们需要获取要滚动到顶部的视图项的顶部坐标; 3.最后我们需要做计算的偏移量

recyclerView.scrollBy(0, offset);

200只是示例硬编码整数值,如果视图所有者项不存在,您可以使用它,因为这也是可能的。

© www.soinside.com 2019 - 2024. All rights reserved.