RecyclerView滑动到指定Position

来源:互联网 发布:电脑指令mac地址修改 编辑:程序博客网 时间:2024/05/18 00:41

Question

最近在写 SideBar 的时候遇到一个问题,当执行 Recyclerview 的 smoothScrollToPosition(position) 的时候,Recyclerview 看上去并没有滚动到指定位置。

Analysis

当然,这并不是方法的bug,而是 smoothScrollToPosition(position) 的执行效果有三种情况,需要区分。

  • 目标position在第一个可见项之前 。
    这种情况调用smoothScrollToPosition能够平滑的滚动到指定位置,并且置顶。

  • 目标position在第一个可见项之后,最后一个可见项之前。
    这种情况下,调用smoothScrollToPosition不会有任何效果···

  • 目标position在最后一个可见项之后。
    这种情况调用smoothScrollToPosition会把目标项滑动到屏幕最下方···

Solution

鉴于这三种情况,我想大多数情况下都无法满足我们的滑动要求。为了实现 Recyclerview 把指定 item 滑动到屏幕顶端的需求,我们需要对上面三种情况分别处理。

    /** 目标项是否在最后一个可见项之后*/    private boolean mShouldScroll;    /** 记录目标项位置*/    private int mToPosition;    /**     * 滑动到指定位置     * @param mRecyclerView     * @param position     */    private void smoothMoveToPosition(RecyclerView mRecyclerView, final int position) {        // 第一个可见位置        int firstItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(0));        // 最后一个可见位置        int lastItem = mRecyclerView.getChildLayoutPosition(mRecyclerView.getChildAt(mRecyclerView.getChildCount() - 1));        if (position < firstItem) {            // 如果跳转位置在第一个可见位置之前,就smoothScrollToPosition可以直接跳转            mRecyclerView.smoothScrollToPosition(position);        } else if (position <= lastItem) {            // 跳转位置在第一个可见项之后,最后一个可见项之前            // smoothScrollToPosition根本不会动,此时调用smoothScrollBy来滑动到指定位置            int movePosition = position - firstItem;            if (movePosition >= 0 && movePosition < mRecyclerView.getChildCount()) {                int top = mRecyclerView.getChildAt(movePosition).getTop();                mRecyclerView.smoothScrollBy(0, top);            }        }else {            // 如果要跳转的位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置            // 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,执行上一个判断中的方法            mRecyclerView.smoothScrollToPosition(position);            mToPosition = position;            mShouldScroll = true;        }    }

再通过onScrollStateChanged控制再次调用smoothMoveToPosition

        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);                if (mShouldScroll){                    mShouldScroll = false;                    smoothMoveToPosition(mRecyclerView,mToPosition);                }            }        });    }

目前这个解决方法有两个已知的问题

  1. 当目标项在最后一个可见项之后的时候,由于我们先执行smoothScrollToPosition方法,然后在OnScrollListener中执行smoothMoveToPosition方法,在滑动的时候不够连贯。
  2. 在手动滑动的时候执行该方法,会有极小的概率滑动的位置出现偏差。

如果你有更好解决办法,希望不吝指教。

0 0
原创粉丝点击