用startSmoothScroll实现RecyclerView滚动到指定位置并置顶,含有动画。

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);
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值