Recyclerview实现按页滑动,超过一半width,默认滑到下一页,否则就停留在当前页

package com.pengzhang.helper;
 
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MotionEvent;
import android.view.View;
 
/**
 * description:
 * author:pz
 * 时间:2017/4/19 :22:24
 */
 
public class PagingScrollHelper {
    private RecyclerView mRecyclerView = null;
    private ValueAnimator mAnimator = null;
    private MyOnScrollListener mOnScrollListener = new MyOnScrollListener();
    private onPageChangeListener mOnPageChangeListener;
    private MyOnFlingListener mOnFlingListener = new MyOnFlingListener();
    //当前滑动距离
    private int offsetY = 0;
    private int offsetX = 0;
 
    //按下屏幕点
    private int startY = 0;
    private int startX = 0;
 
    //最后一个可见 view 位置
    private int lastItemPosition = -1;
    //第一个可见view的位置
    private int firstItemPosition = -2;
    //总 itemView 数量
    private int totalNum;
    //滑动至耨一页
    private int pageNum = -1;
    //一次滚动 n 页
    private int indexPage;
 
    private enum ORIENTATION {
        HORIZONTAL, VERTICAL, NULL
    }
 
    private ORIENTATION mOrientation = ORIENTATION.HORIZONTAL;
 
    public void setUpRecycleView(RecyclerView recycleView) {
        if (recycleView == null) {
            throw new IllegalArgumentException("recycleView must be not null");
        }
        mRecyclerView = recycleView;
        recycleView.setOnFlingListener(mOnFlingListener);
        recycleView.setOnScrollListener(mOnScrollListener);
        recycleView.setOnTouchListener(mOnTouchListener);
        updateLayoutManger();
    }
 
    public void updateLayoutManger() {
        RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
        if (layoutManager != null) {
            if (layoutManager.canScrollVertically()) {
                mOrientation = ORIENTATION.VERTICAL;
            } else if (layoutManager.canScrollHorizontally()) {
                mOrientation = ORIENTATION.HORIZONTAL;
            } else {
                mOrientation = ORIENTATION.NULL;
            }
            if (mAnimator != null) {
                mAnimator.cancel();
            }
            startX = 0;
            startY = 0;
            offsetX = 0;
            offsetY = 0;
 
        }
 
    }
 
    private class MyOnFlingListener extends RecyclerView.OnFlingListener {
 
        @Override
        public boolean onFling(int velocityX, int velocityY) {
            if (mOrientation == ORIENTATION.NULL) {
                return false;
            }
            //获取开始滚动时所在页面的index
            int page = getStartPageIndex();
 
            //记录滚动开始和结束的位置
            int endPoint = 0;
            int startPoint = 0;
 
            //如果是垂直方向
            if (mOrientation == ORIENTATION.VERTICAL) {
                //开始滚动位置,当前开始执行 scrollBy 位置
                startPoint = offsetY;
                if(velocityY==Integer.MAX_VALUE){
                    page +=indexPage;
                }else if (velocityY < 0) {
                    page--;
                } else if (velocityY > 0) {
                    page++;
                } else if (pageNum != -1) {
                    startPoint=0;
                    page = pageNum-1;
                }
                //更具不同的速度判断需要滚动的方向
                //一次滚动一个 mRecyclerView 高度
                endPoint = page * mRecyclerView.getHeight();
 
            } else {
                startPoint = offsetX;
                if(velocityX==Integer.MAX_VALUE){
                    page +=indexPage;
                }else if (velocityX < 0) {
                    page--;
                } else if (velocityX > 0) {
                    page++;
                } else if (pageNum != -1) {
                    startPoint=0;
                    page = pageNum-1;
                }
                endPoint = page * mRecyclerView.getWidth();
 
            }
            //使用动画处理滚动
            if (mAnimator == null) {
                mAnimator = ValueAnimator.ofInt(startPoint, endPoint);
                mAnimator.setDuration(300);
                mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        int nowPoint = (int) animation.getAnimatedValue();
 
                        if (mOrientation == ORIENTATION.VERTICAL) {
                            int dy = nowPoint - offsetY;
                            if (dy == 0) return;
                            //这里通过RecyclerView的scrollBy方法实现滚动。
                            mRecyclerView.scrollBy(0, dy);
                        } else {
                            int dx = nowPoint - offsetX;
                            mRecyclerView.scrollBy(dx, 0);
                        }
                    }
                });
                mAnimator.addListener(new AnimatorListenerAdapter() {
                    //动画结束
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        //回调监听
                        if (null != mOnPageChangeListener) {
                            mOnPageChangeListener.onPageChange(getPageIndex());
                        }
                        startY = offsetY;
                        startX = offsetX;
                        //滚动完成,进行判断是否滚到头了或者滚到尾部了
                        RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
                        //判断是当前layoutManager是否为LinearLayoutManager
                        // 只有LinearLayoutManager才有查找第一个和最后一个可见view位置的方法
                        if (layoutManager instanceof LinearLayoutManager) {
                            LinearLayoutManager linearManager = (LinearLayoutManager) layoutManager;
                            //获取最后一个可见view的位置
                            lastItemPosition = linearManager.findLastVisibleItemPosition();
                            //获取第一个可见view的位置
                            firstItemPosition = linearManager.findFirstVisibleItemPosition();
 
                        }
                        totalNum = mRecyclerView.getAdapter().getItemCount();
                        if (totalNum == lastItemPosition + 1) {
                            updateLayoutManger();
                        }
                        if (firstItemPosition == 0) {
                            updateLayoutManger();
                        }
                    }
                });
            } else {
                mAnimator.cancel();
                mAnimator.setIntValues(startPoint, endPoint);
            }
 
            mAnimator.start();
 
            return true;
        }
    }
 
    private class MyOnScrollListener extends RecyclerView.OnScrollListener {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            if (newState == RecyclerView.SCROLL_STATE_IDLE && mOrientation != ORIENTATION.NULL) {
                boolean move;
                int vX = 0, vY = 0;
                if (mOrientation == ORIENTATION.VERTICAL) {
                    int absY = Math.abs(offsetY - startY);
                    //如果滑动的距离超过屏幕的一半表示需要滑动到下一页
                    move = absY > recyclerView.getHeight() / 2;
                    vY = 0;
                    if (move) {
                        vY = offsetY - startY < 0 ? -1000 : 1000;
                    }
                } else {
                    int absX = Math.abs(offsetX - startX);
                    move = absX > recyclerView.getWidth() / 2;
                    if (move) {
                        vX = offsetX - startX < 0 ? -1000 : 1000;
                    }
                }
                mOnFlingListener.onFling(vX, vY);
            }
        }
 
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            //滚动结束记录滚动的偏移量
            //记录当前滚动到的位置
            offsetY += dy;
            offsetX += dx;
        }
    }
 
    private MyOnTouchListener mOnTouchListener = new MyOnTouchListener();
 
 
    private class MyOnTouchListener implements View.OnTouchListener {
 
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return false;
        }
    }
 
    //获取当前滚动的页数
    private int getPageIndex() {
        int p = 0;
        if (mOrientation == ORIENTATION.VERTICAL) {
            //当前滚动到的位置除以屏幕高度的整数就是当前滚动的位置
            p = offsetY / mRecyclerView.getHeight();
        } else {
            p = offsetX / mRecyclerView.getWidth();
        }
        return p;
    }
 
    private int getStartPageIndex() {
        int p = 0;
        if (mOrientation == ORIENTATION.VERTICAL) {
            //当前按下坐标大对应的页数
            p = startY / mRecyclerView.getHeight();
        } else {
            p = startX / mRecyclerView.getWidth();
        }
        return p;
    }
 
    public void setOnPageChangeListener(onPageChangeListener listener) {
        mOnPageChangeListener = listener;
    }
 
    public interface onPageChangeListener {
        void onPageChange(int index);
    }
 
    public void setPageNum(int page) {
        mRecyclerView.scrollToPosition(0);
        updateLayoutManger();
        this.pageNum = page;
        mOnFlingListener.onFling(0, 0);
    }
 
    public void setIndexPage(int indexPage){
        this.indexPage=indexPage;
        mOnFlingListener.onFling(Integer.MAX_VALUE,Integer.MAX_VALUE);
    }
 
}

上述这个

PagingScrollHelper.java实现该滑动效果。
 
 

调用处 还是要设置LayoutManager, adapter,再调用方法setUpRecycleView()

  private void initView() {
        appsAdapter = new AppsAdapter(appInfos);
        StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.HORIZONTAL);
        laucherRecyclerView.setLayoutManager(layoutManager);
        pagingScrollHelper = new PagingScrollHelper();
        pagingScrollHelper.setUpRecycleView(laucherRecyclerView);
        laucherRecyclerView.setAdapter(appsAdapter);
    }

流程: 

 

图不是很清楚,所以这里再用文字表述一下

继承

RecyclerView.OnScrollListener----> 重写

onScrollStateChanged()---->在方法中判断移动的距离>1/2width?---->是: 再判断左移还是右移(移动后的x坐标和初始坐标比较),超过了1/2,则调用onFiling(x, 0),进行移动-->未超过,维持现状

onFiling()也是重写的,具体是

extends RecyclerView.OnFlingListener, 方法里面的内容是page++/page--(页数的加减),外加动画效果移动

 

转载:https://blog.csdn.net/qq_26787409/article/details/119351507

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值