简单实现上拉加载的RecyclerView

本文介绍如何基于RecyclerView实现上拉加载功能,通过监听滑动状态、判断是否到达最后一条数据、显示加载视图及加载数据四个步骤,实现了一个简易但实用的上拉加载功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

Google提供了下拉刷新控件,但是并没有提供上拉加载的控件。即使是没有提供,我们一样可以实现。毕竟Android开放性强。目前有很多第三方开源的控件,做的非常优秀,也不外乎上拉加载。也正因为如此,很多人只停留在用轮子,而没思考轮子怎么造成的。用谁都会用,但是又有几个人知道其中实现原理。归回主题,今天打造一个简单的轮子,也可以不是轮子。基于RecyclerView的上拉加载。

思路

上拉,手指向上滑动。加载,最后一条数据的时候显示加载视图,并且加载下一页的数据。

滑动、最后一条数据、显示加载视图、加载数据。也就这四步。

预备

首先写出RecyclerView常用的方式。

    RecyclerView rvMain =(RecyclerView) findViewById(R.id.rv_main);
    rvMain.setLayoutManager(new LinearLayoutManager(this));
    rvMain.setAdapter(adapter = new Adapter(10));

监听滑动

RecyclerView实例下有addOnScrollListener方法,用于监听RecyclerView滑动的回调。实现OnScrollListener类,这里只需要覆盖onScrollStateChanged这方法就好了。

    rvMain.addOnScrollListener(new RecyclerView.OnScrollListener() {
           @Override
           public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
           }
       });

最后一条数据

已知道向上滑动,这时就要判断是否最后一条数据。RecyclerView类有一个canScrollVertically方法,表示能否垂直滑动,参数direction表示滑动的方向,1表示往上滑,滑不动就返回false,意味着到底了。-1表示往下滑,滑不动就返回false,意味着到顶了。

    boolean canScrollVertically(int direction)// 1往上滑 -1往下滑

加到判断中

    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
         if (!recyclerView.canScrollVertically(1)) {
             Log.e("tag", "向上滑动,显示到最后一个item");
         }
     }

显示加载视图

前两步都很简单,到了这步也很简单,只是比较繁琐。RecyclerView不负责视图,只能去Adapter搞事情了。

首先创建一个加载视图的ViewHolder类,加载视图你想显示什么样都可以。

    class LoadMoreViewHolder extends RecyclerView.ViewHolder 

然后在Adapter里面标记两种类型,分别创建不同ViewHolder。如果多type不熟悉,可以先看看RecyclerView的资料。

    private static final int TYPE_NORMAL = 1;//显示真正视图的类型
    private static final int TYPE_LOADMORE = -1;//显示加载视图的类型

    //分别创建ViewHolder
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_NORMAL) {
            return new NormalViewHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_normal, parent, false));
        }
        loadMoreViewHolder = new LoadMoreViewHolder(LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_loadmore, parent, false));//保留下来控制加载视图
        return loadMoreViewHolder;
    }

    //根据位置显示Type
    public int getItemViewType(int position) {
        if (position == count) {//
            return TYPE_NORMAL;
        } else {
            return TYPE_LOADMORE;
        }
    }

    //因为多出一个LoadMore视图,要记得数量上加多一个
    public int getItemCount() {
        return count + 1;
    }

    ...

这样加载视图已经加到最后一个item。但是还没解决滑动底部就显示加载视图。
可以在Adapter提供对外的方法,控制LoadMoreViewHolder 中的item显示与隐藏。不能直接隐藏,还要把ItemView的高度和宽度设置为0,不然隐藏item还多出一块空白。

class LoadMoreViewHolder extends RecyclerView.ViewHolder {

        private View itemView;
        private int height;
        private int width;

        public LoadMoreViewHolder(View itemView) {
            super(itemView);
            this.itemView = itemView;
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) itemView.getLayoutParams();
            height = params.height;//保存高度
            width = params.width;//保存宽度
        }

        public void setLoadMore(boolean loadMore) {
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) itemView.getLayoutParams();
            if (loadMore) {
                //如果显示,就重新把高宽给回itemView
                params.width = width;
                params.height = height;
                itemView.setVisibility(View.VISIBLE);
            } else {
                //如果隐藏,就取掉高宽度
                params.width = 0;
                params.height = 1;//!!!这里要注意了,不能设置0,不然canScrollVertically方法找不到最后一个,永远为true
                itemView.setVisibility(View.GONE);
            }
            itemView.setLayoutParams(params);
        }
    }

加载数据

到这步基本是完成了。现在来优化一下onScrollStateChanged方法。最好在方法下加个判断canLoadMore 。是否继续加载,数据加载完毕就可以关掉。为了加载的过程中,不能再使用这方法,再加一个isLoading判断。再判断newState是否等于 RecyclerView.SCROLL_STATE_IDLE(滑动停止)。

    rvMain.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                if (!recyclerView.canScrollVertically(1) && canLoadMore && !isLoading
                        && newState == RecyclerView.SCROLL_STATE_IDLE) {
                    adapter.setLoadMore(true);
                    loadData();
              }
           }
     })

    private void loadData() {//模拟2秒后获取数据
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                adapter.addCount(10);
                adapter.setLoadMore(false);
            }
        }, 2000);
    }

最后

这是最简单的上拉加载!可能会有莫名其妙的BUG,之前遇到一个坑,RecyclerView在CoordinatorLayout嵌套下,RecyclerView的onScrolled方法在只调用一次。这是很坑的,这只能无奈把onScrolled方法内的语法写在onScrollStateChanged。执行效果也是一样。当然你也可以将这些封装起来,当作一个库,使用的时候就方便多了。也可以控制显示不同的加载视图,比如网络失败、请求失败、到底了。。

模糊的演示
这里写图片描述

源码在这!!

点击我获得源码

封装之后 github地址 https://github.com/tanxinye/simpleloadmore

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值