RecyclerView滚动到指定位置并置顶

RecyclerView本身提供了几个定位的方法,除了手动滑动的scrollTo,smootScrollTo和scrollBy,smoothScrollBy方法之外,有一个直接滑动到指定位置item的scrollToPosition方法和另一个在此基础上平滑滚动的smoothScrollToPosition方法。但是经实验,该方法只能保证指定位置的item滑动到屏幕可见,如果指定的item本来就已在屏幕可见范围,则不会滑动,并且屏幕外的item滑到可见范围后,还需手动置顶。
常见处理方式
看了网上大多数相关的博客,一般的处理都是将item区分为 在可见范围以上/在可见范围内/在可见范围以下 三种情况,分别进行处理。
1、item在第一个可见item之前,直接用smoothScrollToPosition,则当该item移动到可见范围时,它就在RecyclerView顶部
2、item在可见范围内,即在第一个可见item之后,最后一个可见item之前,那么这时scrollToPosition失效,需要手动计算该item的view距离顶部的距离,用scrollBy自行移动到置顶位置
3、item在最后一个可见item之后,用smoothScrollToPosition滑动到可见范围 (此时该item在最后一个位置),再获取该item的view,计算到顶部距离,再监听RecyclerView的滑动,对其进行二次滑动到顶部
贴上该方法主要的实现代码:
//标记是否需要二次滑动
    private boolean shouldMove;
    //需要滑动到的item位置
    private int mPosition;
     * RecyclerView滑动到指定item函数
    private void smoothMoveToPosition(RecyclerView recyclerView, final int position) {
        // 获取RecyclerView的第一个可见位置
        int firstItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(0));
        // 获取RecyclerView的最后一个可见位置
        int lastItem = recyclerView.getChildLayoutPosition(recyclerView.getChildAt(mRecyclerView.getChildCount() - 1));
        if (position < firstItem) {
            // 指定item在第一个可见item之前
            recyclerView.smoothScrollToPosition(position);
        } else if (position <= lastItem) {
            // 指定item在可见范围内,即在第一个可见item之后,最后一个可见item之前
            int position = position - firstItem;
            if (position >= 0 && position < recyclerView.getChildCount()) {
                // 计算指定item的view到顶部的距离
                int top = recyclerView.getChildAt(position).getTop();
                // 手动滑动到顶部
                recyclerView.smoothScrollBy(0, top);
        } else {
            // 指定item在最后一个可见item之后,用smoothScrollToPosition滑动到可见范围
            // 再监听RecyclerView的滑动,对其进行二次滑动到顶部
            recyclerView.smoothScrollToPosition(position);
            mPositon = position;
            shouldMove = true;
 * 监听RecyclerView的滑动,对需要进行二次滑动的item进行滑动
 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if ( shouldMove && RecyclerView.SCROLL_STATE_IDLE == newState) {
                    shouldMove = false;
                    smoothMoveToPosition(mRecyclerView, mPosition);
        });
本文推荐的另外一种处理方式
通过上面的代码可以看出来,这种处理方式比较麻烦,而且处理逻辑需要分成两块,并不够直观。因此点开源码,发现实际上RecyclerView在用smoothScrollToPosition函数时,是创建了一个LinearSmoothScroller:
再继续点开看:
一进入文件就发现了SNAP_TO_START这个参数,注释意思是,将子view与父view左对齐或顶部对齐,其中是左对齐还是顶部对齐,是根据LayoutManager是horizontal还是vertical决定,因此重写LinearSmoothScroller,设置该参数即可实现置顶。
public class TopSmoothScroller extends LinearSmoothScroller {
    TopSmoothScroller(Context context) {
        super(context);
    @Override
    protected int getHorizontalSnapPreference() {
        return SNAP_TO_START;
    @Override
    protected int getVerticalSnapPreference() {
        return SNAP_TO_START;  // 将子view与父view顶部对齐
之后获取RecyclerView的LayoutManager,调用startSmoothScroll即可
final TopSmoothScroller mTopScroller = new TopSmoothScroller(this);
mTopScroller.setTargetPosition(position);
mRecyclerView.getLayoutManager.startSmoothScroll(mTopScroller);
                    RecyclerView滚动到指定位置并置顶RecyclerView本身提供了几个定位的方法,除了手动滑动的scrollTo,smootScrollTo和scrollBy,smoothScrollBy方法之外,有一个直接滑动到指定位置item的scrollToPosition方法和另一个在此基础上平滑滚动的smoothScrollToPosition方法。但是经实验,该方法只能保证指定位置的item滑动到屏幕可见,如果指定的item本来就已在屏幕可见范围,则不会滑动,并且屏幕外的item滑到可见范围后,还
RecyclerView在安卓开发中非常实用,而且简单易用,但是在实际开发中一直有一个问题困扰着我,就是定位问题,实际的项目中总是会遇到这样的需求:检索RecyclerView的某一项(各个项的高度不确定),然后定位这一项,将它显示在部。用RecyclerView的默认移动的方法并不能实现这一点(个人感觉官方可能出于性能考虑才不实现这一点)。这篇博客就讲解下我个人是如何实现这个需求的。
Demo演示
敲代码前的思考
RecyclerView提供的用于控制移动的方法有2个 
– scrollToPosition(int) 
这个方法的作用是显示指定项,就是把你想的项显示出来,但是
				
scrollToPositionWithOffset:offset - 项目视图的起始边缘与RecyclerView的起始边缘之间的距离(以像素为单位)。这里相比scrollToPosition,我们就可以设偏移量: 如果offset = 0,我们可以理解为将目标Item刻意的滚动部第一个可见位置,如果offset = 100,将目标Item刻意的滚动到距离部第一个可见位置往下偏移100px,然后以此类推... 如果只是想使某个位置可见,请使用scrollToPosition(int)
问题:常见的滑动到最后一行但是显示不全的情况? 1.普通场景下滑动到最后一行 recyclerView.scrollToPosition(mAdapter.getData().size() - 1); 2.弹出软键盘时滑动到最后一行 recyclerView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { if (bottom
import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView
其实Android RecyclerView组件已经自带了移动方法: RecyclerView.scrollToPosition(position) //没有动画效果 但是这个方法没有动画效果,很生硬,直接就滑动过去了,下面来看一个有滑动动画效果的: val smoothScroller= object : androidx.recyclerview.widget.LinearSmoothScro...
最近博主发现让RecyclerView滑动到某一位置的博客一大堆,抄的是完全一模一样。此外,虽然这些博客“解决”了这些问题,但这种解决方案过于浅显、粗暴,甚至都违背了开发思想。遂在此纠正这种错误。 RecyclerView提供了几种移动的方法 scrollToPosition scrollTo scrollBy smoothScrollBy smoothScrollToPosit...
class CenterLayoutManager extends LinearLayoutManager { public CenterLayoutManager(Context context) { super(context); @Override public void smoothScrol...
前言:使用RecyclerView时,调用smoothScrollToPostion()方法滑动到指定位置,但是条目很多时滑动的很慢,本篇文章就旨在实现RecyclerView的快速滑动。先介绍如何实现,然后再介绍原理。1. 实现代码 创建FastScrollLinearLayoutManager,继承LinearLayoutManager 复写smoothScrollToPosition()方法,
if (hwnd != NULL) SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); // 窗口 return 0; 上面的代码通过调用 FindWindow 函数获取窗口句柄,然后通过调用 SetWindowPos 函数将窗口。 如果需要取消窗口,可以将参数 HWND_TOPMOST 改为 HWND_NOTOPMOST。 此外,还需要注意的是,在窗口时,可能会出现一些问题,例如窗口没有正确地渲染,或者窗口的控件无法响应鼠标事件。这可能是由于窗口的 Z 顺序问题造成的。因此,在窗口时,需要注意检查是否存在这类问题,并适当地调整窗口的 Z 顺序以避免这类问题。 Kafka启动出现Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Pr
count does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manu weixin_46055842: 牛的牛的,精确打击 Kafka启动出现Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Pr HadwinLing: 你好,请问你解决了吗 java 为文件及文件夹添加权限 JSON_ZJS: 可以忽略,只是一个日志,直接使用lombok就行log4j都可以。 用startSmoothScroll实现RecyclerView滚动到指定位置并置顶,含有动画。 qczg_wxg: 解决我的问题了,作者真牛