RecyclerView 上拉加载 PullToRefreshRecyclerView

本文介绍了如何在RecyclerView中实现上拉加载功能,通过自定义PullToRefreshRecyclerView组件,避免了在每个使用RecyclerView的地方写重复代码。通过重写onMeasure方法调整布局高度,以及拦截和分发滑动事件,实现平滑的上拉加载效果。同时解决了与SwipeRefreshLayout结合使用时可能出现的滑动冲突问题。
摘要由CSDN通过智能技术生成

设计思路

ListView 上拉加载很容易实现,监听 ListView 滑动到底部,显示 FootView 即可,但是 RecyclerView 没有 addFootView(View view) 这个方法,有一种方案是在 adapter 中加一个 itemView 用于显示 FootView,但是这样做就得每一个使用到 RecyclerView 的地方都写一遍重复代码,而且不能适配多种类型的 LayoutManager,所以 RecyclerView 就需要另外一种思路来实现,我的解决方案是:自定义 PullToRefreshRecyclerView 继承 FrameLayout,将 RecyclerView 与 FootView 添加到 PullToRefreshRecyclerView 中,上拉时显示 FootView。
效果如下:

预览图
## 具体方案 布局文件中很简单,一个 FrameLayout 内部放一个 RecyclerView 和 一个 FootView,布局文件如下: ``` <?xml version="1.0" encoding="utf-8"?> ``` 这个布局的效果如下图:
预览图

可以看到有个很明显的问题,FootView 是一直在屏幕内部的,即使隐藏掉滑动到底部在显示效果也很差劲,我的解决方案是重写 PullToRefreshRecyclerView 的 onMeasure 方法,将 PullToRefreshRecyclerView 高度设置为屏幕高度加上 FootView 的高度,上拉时使用 scrollTo 方法显示 FootView。
onMeasure 方法如下:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    final int height = getMeasuredHeight() + footViewHeight;
    setMeasuredDimension(getMeasuredWidth(), height);

    LayoutParams rootLP = (LayoutParams) rootView.getLayoutParams();
    rootLP.height = height;
    rootView.setLayoutParams(rootLP);//设置 FootView的高度

    LayoutParams recyclerLp = (LayoutParams) recyclerView.getLayoutParams();
    recyclerLp.height = height - footViewHeight;
    recyclerView.setLayoutParams(recyclerLp);//将 RecyclerView 的高度设置为屏幕高度
}

这样基本布局就完成了,然后就是对滑动事件的拦截与分发,如果滑动到底部则拦截事件,并且根据滑动距离来计算 scrollTo 的移动距离,具体代码如下:


@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (recyclerView == null || recyclerView.getChildCount() == 0)
        return super.onInterceptTouchEvent(ev);
    if(isLoading) return true;//如果正在加载中则拦截滑动事件
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            lastDownY = (int) ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            int lastPosition = -1;
            //以下代码用于获取当前 RecyclerView 中显示的最后一个 position
            RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
            if (layoutManager instanceof GridLayoutManager) {
                lastPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
            } else if (layoutManager instanceof LinearLayoutManager) {
                lastPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            } else if (layoutManager instanceof StaggeredGridLayoutManager) {
                int[] lastPositions = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
                ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(lastPositions);
                lastPosition = findMax(lastPositions);
            }

            int offerY = (int) ev.getY() - lastDownY;
            if (offerY < 0) {
              //如果正在上拉
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值