RecyclerView下拉刷新和上拉加载更多实现

在Android开发中,RecyclerView算是使用频率非常广泛的组件了吧,在这里对RecyclerView比较常用的下拉刷新和上拉加载更多的功能实现做个记录,方便以后查看。
在这里下拉刷新使用的是官方提供的SwipeRefreshLayout,然后上拉加载更多的功能使用的是第三方库BaseRecyclerViewAdapterHelper实现。

依赖导入

在项目build.gradle文件中添加以下代码导入依赖:

implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.46'
implementation group: 'androidx.recyclerview', name: 'recyclerview', version: '1.1.0-alpha01'
下拉刷新和上拉加载更多实现
  • 实体类UserData
public class UserData {
    private String userName;

    public UserData() {
    }

    public UserData(String userName) {
        this.userName = userName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}
  • RecyclerView对应的Adapter
import android.graphics.Color;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;

import java.util.List;

import androidx.annotation.Nullable;

public class MainAdapter extends BaseQuickAdapter<UserData, BaseViewHolder> {
    public MainAdapter(int layoutResId, @Nullable List<UserData> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, UserData item) {
        int adapterPosition = helper.getAdapterPosition();
        if (adapterPosition % 2 == 0) {
            helper.setBackgroundColor(R.id.rlContent, Color.RED);
        }else {
            helper.setBackgroundColor(R.id.rlContent, Color.YELLOW);
        }
        helper.setText(R.id.tvName, item.getUserName());
    }
}
  • RecyclerView对应的Adapter布局文件recycler_item_demo.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/rlContent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tvName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:padding="20dp"
        android:text="测试"
        android:textColor="#333333"
        android:textSize="30dp" />

</RelativeLayout>
  • MainActivity
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;

import com.chad.library.adapter.base.BaseQuickAdapter;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    private SwipeRefreshLayout swipeRefreshLayout;
    private RecyclerView recyclerView;

    private List<UserData> userDatas = new ArrayList<>();
    private int count = 0;
    private int loadMoreCount = 0;
    private MainAdapter mainAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
        recyclerView = findViewById(R.id.recyclerView);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        mainAdapter = new MainAdapter(R.layout.recycler_item_demo, userDatas);
        mainAdapter.setLoadMoreView(new CustomLoadMoreView());
        //设置RecyclerView条目点击事件
        mainAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                UserData item = mainAdapter.getItem(position);
                Log.e(MainActivity.this.getClass().getSimpleName(), "点击条目: " + position + "----userName: " + item.getUserName());
            }
        });
        mainAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
            @Override
            public void onLoadMoreRequested() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        List<UserData> userDataList = getDatas(false);

                        if (loadMoreCount == 1) {
                            //正常加载更多,还有下一页
                            mainAdapter.addData(userDataList);
                            mainAdapter.loadMoreComplete();
                        } else if (loadMoreCount == 2) {
                            //返回加载失败
                            mainAdapter.loadMoreFail();
                        } else if (loadMoreCount == 3) {
                            //加载到最后
                            mainAdapter.addData(userDataList.subList(0, 6));
                            mainAdapter.loadMoreEnd();
                        }
                    }
                }, 3000);
            }
        }, recyclerView);
        recyclerView.setAdapter(mainAdapter);

        swipeRefreshLayout.setOnRefreshListener(this);
        onRefresh();
    }

    private List<UserData> getDatas(boolean isRefresh) {
        if (isRefresh) {
            count = 0;
        }

        List<UserData> dataList = new ArrayList<>();
        for (int i = count; i < count + 10; i++) {
            if (isRefresh) {
                loadMoreCount = 0;
                dataList.add(new UserData("下拉刷新数据" + i));
            } else {
                dataList.add(new UserData("上拉加载更多数据" + i));
            }
        }

        if (!isRefresh) {
            loadMoreCount++;
        }

        count += 10;

        return dataList;
    }

    @Override
    public void onRefresh() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                List<UserData> userDataList = getDatas(true);
                mainAdapter.setNewData(userDataList);
                mainAdapter.loadMoreComplete();
                swipeRefreshLayout.setRefreshing(false);
            }
        }, 3000);
    }
}

以上代码中RecyclerView的数据集使用假数据测试,并且模拟第一次上拉加载更多成功,第二次上拉加载失败,点击失败重试,最后加载完毕(即没有更多数据)

  • MainActivity的布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
  • 运行结果截图
    运行结果截图
注意事项

加载更多的View布局是可以自定义的,自定义调用的方法:

mainAdapter.setLoadMoreView(new CustomLoadMoreView());
  • CustomLoadMoreView
import com.chad.library.adapter.base.loadmore.LoadMoreView;
public final class CustomLoadMoreView extends LoadMoreView {

    @Override
    public int getLayoutId() {
        return R.layout.view_load_more;
    }

    @Override
    protected int getLoadingViewId() {
        return R.id.load_more_loading_view;
    }

    @Override
    protected int getLoadFailViewId() {
        return R.id.load_more_load_fail_view;
    }

    @Override
    protected int getLoadEndViewId() {
        return R.id.load_more_load_end_view;
    }
}
  • 加载更多布局文件view_load_more.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_40">

    <LinearLayout
        android:id="@+id/load_more_loading_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:visibility="visible"
        android:orientation="horizontal">

        <ProgressBar
            android:id="@+id/pb_footer"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp" />

        <TextView
            android:id="@+id/tv_footer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="正在加载中..." />
    </LinearLayout>

    <FrameLayout
        android:id="@+id/load_more_load_fail_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">


        <TextView
            android:id="@+id/tv_prompt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/brvah_load_failed"/>

    </FrameLayout>

    <FrameLayout
        android:id="@+id/load_more_load_end_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/brvah_load_end"
            android:textColor="@android:color/darker_gray"/>
    </FrameLayout>
</FrameLayout>

BaseRecyclerViewAdapterHelper的功能不仅仅于此,后续再继续补充。

猜你喜欢

转载自blog.csdn.net/weixin_44247225/article/details/87791472