RecyclerView 滑动到指定位置的终极方案

最近有个奇葩需求,顶部有可以切换的 TabLayout,原本下面用 ViewPager 实现,可以左右滑动,后来说需求根据用户切换 Tab 定位到相应的位置,(个人感觉体验不是很好,用户还得用手去点tab),无奈只好改了,我记RecyclerView 有个smoothScrollToPosition(position) 可以实现定位功能,我加了上去之后效果非常差,有时候还不滚动,后来查了一些资料,使用这个方法是有问题的,

需要分情况处理:

  • 跳转位置在第一个可见位置之前,使用smoothScrollToPosition
  • 跳转位置在第一个可见位置之后,最后一个可见项之前
  • 跳转位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置

要分为以上三种情况,最终通过smoothScrollToPosition结合smoothScrollBy实现,直接贴伪代码如下:

—— 注释部分代码是属于业务逻辑功能,可忽视

   /**
     * 移动到对应的位置
     *
     * @param position tab 的下标
     */
    private void move(int position) {
//        String proMenuId = proMenuBeans.get(position).getId();
//        LogUtils.d("proMenuId:" + proMenuId);
//        //体系列表的下标
//        int index = 0;
//        for (SystemBean systemBean : systemList) {
//            if (systemBean.getProjectid().equals(proMenuId)) {
//                LogUtils.d("systemList Id:" + systemBean.getProjectid());
//                index = systemList.indexOf(systemBean);
//                LogUtils.d("systemList Index" + index);
//            }
//        }
//        LogUtils.d("list 中 索引的位置:" + index);


        smoothMoveToPosition(mRecyclerView, index);



    }
  • 滑动到指定位置:
 //目标项是否在最后一个可见项之后
    private boolean mShouldScroll;
    //记录目标项位置
    private int mToPosition;

    /**
     * 滑动到指定位置
     */
    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) {
            // 第二种可能:跳转位置在第一个可见位置之后,最后一个可见项之前
            int movePosition = position - firstItem;
            if (movePosition >= 0 && movePosition < mRecyclerView.getChildCount()) {
                int top = mRecyclerView.getChildAt(movePosition).getTop();
                // smoothScrollToPosition 不会有效果,此时调用smoothScrollBy来滑动到指定位置
                mRecyclerView.smoothScrollBy(0, top);
            }
        } else {
            // 第三种可能:跳转位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置
            // 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,执行上一个判断中的方法
            mRecyclerView.smoothScrollToPosition(position);
            mToPosition = position;
            mShouldScroll = true;
        }
    }
  • 再通过监听 RecyclerView 的滑动事件,控制再次调用smoothMoveToPosition。

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

以上就是伪代码,很简单,完美解决了我们遇到的问题,OK去试试吧~~

你可能感兴趣的:(【Android,进阶】)