首页 文章

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

提问于
浏览
67

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

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

但是,这突然将项目移动到顶部位置 . 我想移动到项目的顶部 smoothly .

我也尝试过:

recyclerView.smoothScrollToPosition(position);

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

6 回答

  • 3

    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);
    
  • 113

    为此,您必须创建自定义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项目的顶部 .

    希望这可以帮助 .

  • 0

    我发现滚动 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);
    
  • 95

    我们可以这样试试

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

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

    A NOTE 这里 - 如果您的项目(您要在列表顶部滚动的项目)在屏幕上可见,并且您只想自动将其滚动到顶部,这将很有效 . 当列表中的最后一项具有某些操作时会很有用,这会在同一列表中添加新项目,并且您希望将用户集中在新添加的项目上:

    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只是示例硬编码整数值,如果视图所有者项不存在,您可以使用它,因为这也是可能的 .

  • 0

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

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

相关问题