RecyclerView下拉刷新和上拉加載更多實現
轉 https://www.jianshu.com/p/4ea7c2d95ecf
在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的功能不僅僅於此,后續再繼續補充。