SoFunction
Updated on 2025-03-01

Android RecycleView implements pull-down refresh and pull-up loading

Android's drop-down refresh, pull-up loading function, displays the content from page 1 to the current page when turning page, and the content of the current page is currently displayed;

: Page Turning Control

public class PullRefreshRecyclerView extends LinearLayout implements ,  {
 private SwipeRefreshLayout swipeRefreshLayout;
 private RecyclerView recyclerView;
 private LinearLayout footerView;
 private OnPullRefreshListener listener;
 //Is it refreshing? private boolean isRefreshing = false;
 //Is it loading private boolean isLoading = false;
 
 //Is there more data private boolean hasMore = false;
 
 public PullRefreshRecyclerView(Context context) {
 this(context, null);
 }
 
 public PullRefreshRecyclerView(Context context, AttributeSet attrs) {
 super(context, attrs);
 initView(context);
 initListener();
 init();
 }
 
 private void initView(Context context) {
 (context).inflate(.pull_recycler_layout, this, true);
 swipeRefreshLayout = findViewById();
 recyclerView = findViewById();
 footerView = findViewById();
 
 }
 
 private void initListener() {
 (this);
 (new PullableScroll());
 //Prevent the view from sliding when scrolling (this);
 }
 
 private void init() {
 (.holo_green_dark,
  .holo_blue_dark,
  .holo_orange_dark);
 //Hide vertical scroll bar (true);
 // When the item height is fixed, set this option to improve performance (true);
 //Set item animation effect (new DefaultItemAnimator());
 }
 
 public void setHasFixedSize(boolean hasFixedSize) {
 (hasFixedSize);
 }
 
 public void setItemAnimator( animator) {
 (animator);
 }
 
 public void setLayoutManager( layout) {
 (layout);
 }
 
 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
 (verticalScrollBarEnabled);
 }
 
 public void addItemDecoration( decor) {
 (decor);
 
 }
 
 public void setAdapter( adapter) {
 (adapter);
 }
 
 /**
  * Settings listening for pull-down or pull-up events
  *
  * @param listener
  */
 public void setOnPullRefreshListener(OnPullRefreshListener listener) {
  = listener;
 }
 
 /**
  * Set whether there is more data
  *
  * @param hasMore
  */
 public void setHasMore(boolean hasMore) {
  = hasMore;
 }
 
 /**
  * Scroll to top
  */
 public void scrollToTop() {
 (0);
 }
 
 /**
  * Refreshing
  */
 @Override
 public void onRefresh() {
 isRefreshing = true;
 if (listener != null) {
  ();
 }
 
 }
 
 /**
  * Set whether to allow pull-down
  *
  * @param enable
  */
 public void setRefreshEnable(boolean enable) {
 (enable);
 }
 
 /**
  * Check whether it can be refreshed when scrolling
  *
  * @return
  */
 private boolean isRefreshEnable() {
 return !isRefreshing && !isLoading;
 }
 
 /**
  * Loading more
  */
 public void doLoadMore() {
 if (!isLoading && hasMore && !isRefreshing) {
  ();
  isLoading = true;
  //Pull pull-down is prohibited  setRefreshEnable(false);
  if (listener != null) {
  ();
  }
 }
 }
 
 /**
  * Refresh or loading is complete
  */
 public void refreshOrLoadComplete() {
 isRefreshing = false;
 (false);
 isLoading = false;
 ();
 //Add to pull down (true);
 }
 
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 return isRefreshing || isLoading;
 }
 
 public interface OnPullRefreshListener {
 /**
   * Refresh operation
   */
 void onRefresh();
 
 /**
   * Loading operation
   */
 void onLoadMore();
 }
 
 /**
  * Listen to RecycleView slides the bottom or top
  */
 class PullableScroll extends  {
 @Override
 public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
  (recyclerView, dx, dy);
  int lastVisibleItem = 0;
  int firstVisibleItem = 0;
   layoutManager = ();
  int totalItemCount = ();
  if (layoutManager instanceof LinearLayoutManager) {
  LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
  lastVisibleItem = ();
  firstVisibleItem = ();
  } else if (layoutManager instanceof StaggeredGridLayoutManager) {
  StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
  // since may lead to the final item has more than one StaggeredGridLayoutManager the particularity of the so here that is an array
  // this array into an array of position and then take the maximum value that is the last show the position value
  int[] lastPositions = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
  (lastPositions);
  lastVisibleItem = findMax(lastPositions);
  firstVisibleItem = (lastPositions)[0];
  }
 
  pullRefreshEnable(firstVisibleItem, totalItemCount);
  if (isSlideToBottom(recyclerView)) {
  loadMore(dx, dy, lastVisibleItem, totalItemCount);
  }
 
 }
 
 private int findMax(int[] lastPositions) {
  int max = lastPositions[0];
  for (int value : lastPositions) {
  if (value > max) {
   max = value;
  }
  }
  return max;
 }
 }
 
 /**
  * Determine whether it slides to the bottom
  *
  * @param recyclerView
  * @return
  */
 public boolean isSlideToBottom(RecyclerView recyclerView) {
 if (recyclerView == null) {
  return false;
 }
 if (() + ()
  >= ()) {
  return true;
 }
 return false;
 }
 
 private void loadMore(int dx, int dy, int lastVisibleItem, int totalItemCount) {
 //When scrolling to the bottom, more data can be loaded and loaded if (lastVisibleItem >= totalItemCount - 1 && (dx > 0 || dy > 0)) {
  doLoadMore();
 }
 }
 
 private void pullRefreshEnable(int firstVisibleItem, int totalItemCount) {
 //Can be able to pull down and refresh when scrolling to the top if (firstVisibleItem == 0 || totalItemCount == 0) {
  if (isRefreshEnable()) {
  //Add to pull down  setRefreshEnable(true);
  }
 } else {
  //Pull pull-down is prohibited  setRefreshEnable(false);
 }
 }
 
}

: Call

@Route(path = Page.ACTIVITY_PUNISH_LIST)
public class PunishListActivity extends BaseActivity implements ,  {
 private static final String TAG = "PunishListActivity";
 private List<PunishBean> punishBeans = new ArrayList<>();
 private Context mContext;
 private EditText et_punish_searchName;
 private ImageView iv_search;
 private PullRefreshRecyclerView prr_punish;
 private String officeName = "";
 private int pageNo = 1;
 private boolean isLastPage = false;
 private PunishAdapter punishAdapter;
 
 @Override
 public void onBeforeSetContentView() {
 (this, (this, .color_0a5fb6));
 }
 
 @Override
 public int getLayoutResID() {
 return .activity_punish_list;
 }
 
 @Override
 protected CharSequence setActionBarTitle() {
 return "Administrative Penalty";
 }
 @Nullable
 @Override
 public AppBarConfig getAppBarConfig() {
 return mAppBarCompat;
 }
 
 @Override
 public int setActionBarRightVisibility() {
 return ;
 }
 
 @Override
 public CharSequence setActionBarRightText() {
 return "Add to";
 }
 
 public void onResume(){
 ();
 getPunishList("");
 }
 
 @Override
 public void initContentView(@Nullable Bundle savedInstanceState) {
 mContext = ;
 et_punish_searchName = findViewById(.et_punish_searchName);
 iv_search = findViewById(.iv_search);
 iv_search.setOnClickListener(this);
 prr_punish = findViewById(.prr_punish);
 prr_punish.setOnPullRefreshListener(this);
 prr_punish.setHasMore(true);
 }
 
 @Override
 public void initData(@Nullable Bundle savedInstanceState) {
 punishAdapter = new PunishAdapter(mContext,punishBeans);
 LinearLayoutManager manager = new LinearLayoutManager(mContext);
 ();
 prr_punish.setLayoutManager(manager);
 prr_punish.setAdapter(punishAdapter);
// getPunishList();
 }
 
 private void getPunishList(String officeName){
 HashMap<String, Object> baseParam = ();
 ("pageNo", pageNo);
 ("pageSize", 10);
 
 ("officeName", officeName);
 (TAG, WebApi.PUNISH_LIST_URL, baseParam, new StringCallback() {
  @Override
  public void onError(Call call, Exception e, int id) {
  hideWaitDialog();
  (TAG,""+e);
  }
 
  @Override
  public void onResponse(String response, int id) {
  (TAG,"response==="+response);
  try {
   JSONObject object = new JSONObject(response);
   hideWaitDialog();
   if ((int)("code") == 200) {
   JSONObject object1 = ("data");
   PunishBeanList punishBeanList = new Gson().fromJson((),);
   (TAG,"response==="+().size());
   if (pageNo == 1) {
    ();
   }
   if (() != null && ().size() != 0) {
    List<PunishBean> addPunishs = new ArrayList<>();
    addPunishs = ();
    if (() > 0) {
    (addPunishs);
    (addPunishs);
    } else {
    punishBeans = addPunishs;
    (addPunishs);
    }
 
    if (()) {
    isLastPage = true;
    (TAG,"isLastPage = true ");
    }else {
    isLastPage = false;
    (TAG,"isLastPage = false ");
    }
   }
   } else {
   (mContext,("message").toString(),Toast.LENGTH_SHORT).show();
   }
  } catch (JSONException e) {
   ();
  }
  }
 });
 }
 
 @Override
 protected void actionBarRightOnClick() {
 ().build(Page.ACTIVITY_PUNISH_ADD).navigation();
 }
 
 @Override
 public void onClick(View view) {
 switch (()) {
  case .iv_search:
  showWaitDialog();
  officeName = et_punish_searchName.getText().toString();
  pageNo = 1;
  isLastPage = false;
  getPunishList(officeName);
  break;
 }
 }
 
 @Override
 public void onRefresh() {
 prr_punish.refreshOrLoadComplete();
 pageNo = 1;
 getPunishList(officeName);
 prr_punish.setRefreshEnable(true);
 }
 
 @Override
 public void onLoadMore() {
 (TAG,"onLoadMore===================");
 prr_punish.refreshOrLoadComplete();
 if (isLastPage) {
  prr_punish.setRefreshEnable(false);
 } else {
  pageNo += 1;
  getPunishList(officeName);
 }
 }
}

public class PunishAdapter extends <> {
 private Context mContext;
 private List<PunishBean> punishList;
 
 public PunishAdapter(Context mContext, List<PunishBean> punishList) {
  = mContext;
  = punishList;
 }
 
 @NonNull
 @Override
 public  onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
 View view = (mContext).inflate(.punish_item,parent,false);
 PunishHolder punishHolder = new PunishHolder(view);
 return punishHolder;
 }
 
 @Override
 public void onBindViewHolder(@NonNull  holder, int position) {
 PunishBean punishBean = (position);
 PunishHolder punishHolder = (PunishHolder) holder;
 punishHolder.tv_punishName.setText(());
 punishHolder.tv_faren.setText(());
 punishHolder.tv_punishMode.setText(());
 punishHolder.tv_punishReason.setText(());
 punishHolder.tv_punishTime.setText(());
 punishHolder.tv_punishDesc.setText(());
 (new () {
  @Override
  public void onClick(View view) {
  Bundle bundle = new Bundle();
  ("punishDetail",punishBean);
  ().build(Page.ACTIVITY_PUNISH_DETAIL).with(bundle).navigation();
  }
 });
 }
 
 /*
  * Add data to the end of the list
  * */
 public void addMoreData(List<PunishBean> list) {
 int oldSize = ();
 if (list != null && () > 0) {
  ((), list);
  notifyItemRangeInserted(oldSize, ());
 }
 }
 
 /*
  * Fill in new data
  * */
 public void setData(List<PunishBean> data) {
 if (data != null && () > 0) {
  ();
  (data);
  notifyDataSetChanged();
 }
 }
 
 @Override
 public int getItemCount() {
 return punishList==null? 0:();
 }
 
 class PunishHolder extends  {
 private TextView tv_punishName,tv_faren,tv_punishMode,tv_punishReason,tv_punishTime,tv_punishDesc;
 
 public PunishHolder(@NonNull View itemView) {
  super(itemView);
  tv_punishName = (.tv_punishName);
  tv_faren = (.tv_faren);
  tv_punishMode = (.tv_punishMode);
  tv_punishReason = (.tv_punishReason);
  tv_punishTime = (.tv_punishTime);
  tv_punishDesc = (.tv_punishDesc);
 
 }
 }
}

4. Layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:andro
 xmlns:app="/apk/res-auto"
 xmlns:tools="/tools"
 android:fitsSystemWindows="true"
 android:orientation="vertical"
 android:layout_margin="@dimen/px40"
 android:background="@color/color_ffffff"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 tools:context=".">
 <RelativeLayout
 android:
 android:layout_width="match_parent"
 android:layout_marginTop="@dimen/px20"
 android:layout_height="103px"
 android:background="@drawable/bg_radius_blue">
 
 <EditText
  android:
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_marginStart="@dimen/px44"
  android:layout_marginEnd="@dimen/px110"
  android:background="@null"
  android:hint="Please enter the unit name"
  android:inputType="text"
  android:textColor="@color/color_hint"
  android:textColorHint="@color/color_hint"
  android:textSize="@dimen/font_14" />
 
 <ImageView
  android:
  android:layout_width="@dimen/px54"
  android:layout_height="@dimen/px54"
  android:layout_alignParentEnd="true"
  android:layout_centerVertical="true"
  android:layout_marginEnd="@dimen/px50"
  android:src="@drawable/icon_text_search" />
 </RelativeLayout>
 <
 android:
 android:layout_width="match_parent"
 android:layout_height="wrap_content"/>
</LinearLayout>

This article has been sorted out"Android drop-down refresh pull-up loading effect", everyone is welcome to study and research.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.