实现思维
开始之前先废话几句,Android系统没有提供上拉加载的控件,只提供了下拉刷新的SwipeRefreshLayout控件。这个控件我们就不废话,无法实现上拉刷新的功能。现在我们说说上拉加载更多的功能实现
思维步骤:
- 首先需要创建一个叫页尾的布局文件,它用来在列表的最后面显示使用
- 接着我们需要想办法在RecyclerView的适配器里导入这个页尾布局。你的列表内容适配器的普通item该如何实现还是如何实现。
- 为了导入这个页尾布局,我们需要在导入的List长度+1,因为这个页尾布局是另外加入的,需要在getItemCount()这个重写方法里返回List长度上+1。
- 现在就需要判断什么时候滚动到了列表的最后,这个时候我们需要重写一个之前写RecyclerView适配器一般不触及的一个重写方法public int getItemViewType(int position) 。重写它根据position位置返回普通item和页尾item的ViewType。
- 能判断什么时候滚动到最后面后,我们就需要在写RecyclerView适配器一样在onCreateViewHolder方法里导入布局,这里我们可以根据ViewType判断应该导入普通item还是页尾item
- 然后就是处理点击逻辑或者处理刷新逻辑了。这部分就不在详细描述步骤了。看下面的代码
代码部分
页尾布局 pull_up_refresh.xml:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" android:background="@color/colorGray5" android:layout_width="match_parent" android:layout_height="30dp"> <ProgressBar android:id="@+id/footer_progress" android:layout_width="14dp" android:layout_height="14dp" android:layout_marginRight="10dp" android:visibility="gone" android:indeterminateDrawable="@anim/pull_up_ic" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="@id/footer_text" app:layout_constraintBottom_toBottomOf="@id/footer_text" app:layout_constraintRight_toLeftOf="@id/footer_text"/> <TextView android:id="@+id/footer_text" android:text="@string/pull_up_load_more" android:textColor="@color/fontBlack3" android:textSize="@dimen/font_size_14" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/footer_progress" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout>
ProgressBar是刷新加载时候的动画图片 TextView就是文本内容
适配器代码:
public class TNoticeListAdapter extends RecyclerView.Adapter<TNoticeListAdapter.ViewHolder> { private List<TNoticeListBase.Notice> mList; private static final int ITEM_VIEW = 1; private static final int FOOTER_VIEW = 2; public static final int FOOTER_TIPS = 0;//提示上拉加载更多 public static final int FOOTER_ING = 1;//加载中 public static final int FOOTER_ERROR = 2;//网络异常 public static final int FOOTER_FINISH = 3;//没有更多内容 private int footerState = 0; private View mFooterView; private OnFooterClickListener mListener; private int position; public TNoticeListAdapter(List<TNoticeListBase.Notice> list){ this.mList = list; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == ITEM_VIEW){ View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.t_notice_item,parent,false); return new ViewHolder(itemView); }else { mFooterView = LayoutInflater.from(parent.getContext()).inflate(R.layout.pull_up_refresh,parent,false); mFooterView.setOnClickListener(new View.OnClickListener() {//页尾View只在网络异常的时候可以被点击 @Override public void onClick(View v) { if (getFooterState()==FOOTER_ERROR && mListener!=null){ mListener.onClick(); } } }); return new ViewHolder(mFooterView); } } @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { setPosition(position); if (getItemViewType(position) == ITEM_VIEW) { TNoticeListBase.Notice data = mList.get(position); holder.itemTime.setText(String.valueOf(data.time)); holder.itemContent.setText("\t\t" + data.content); return; } if (getItemCount()<10){ //如果传入的list内容少于10 就判断为服务器里没有更多内容了 this.footerState = FOOTER_FINISH; } switch (footerState){ case FOOTER_TIPS: holder.footerText.setText(R.string.pull_up_load_more); holder.footerProgress.setVisibility(View.GONE); break; case FOOTER_ING: holder.footerText.setText(R.string.loading_more_for_you); holder.footerProgress.setVisibility(View.VISIBLE); break; case FOOTER_ERROR: holder.footerText.setText(R.string.network_exception_click_reload); holder.footerProgress.setVisibility(View.GONE); break; case FOOTER_FINISH: holder.footerText.setText(R.string.Theres_nothing_more); holder.footerProgress.setVisibility(View.GONE); break; default: holder.footerText.setText(R.string.pull_up_load_more); holder.footerProgress.setVisibility(View.GONE); break; } } @Override public int getItemViewType(int position) { //根据itemView的位置返回View的类型是普通还是页尾 if (position == getItemCount()-1){ return FOOTER_VIEW; }else { return ITEM_VIEW; } } @Override public int getItemCount() { return mList.size()==0?0:mList.size()+1; } /** * 得到页尾状态 * @return */ public int getFooterState() { return footerState; } /** * 设置页尾状态 * @param footerState */ public void setFooterState(int footerState) { this.footerState = footerState; notifyDataSetChanged(); } /** * 设置页尾点击监听 * @param listener */ public void setFooterClickListener(OnFooterClickListener listener){ this.mListener = listener; } /** * 添加数据方法 * @param list */ public void addData(List<TNoticeListBase.Notice> list){ this.mList = list; } /** * 获取当前位置 * @return */ public int getPosition() { return position; } private void setPosition(int position) { this.position = position; } public class ViewHolder extends RecyclerView.ViewHolder { TextView itemTime; TextView itemContent; TextView footerText; ProgressBar footerProgress; public ViewHolder(@NonNull View itemView) { super(itemView); if (mFooterView!=null && itemView == mFooterView){ footerProgress = (ProgressBar)itemView.findViewById(R.id.footer_progress); footerText = (TextView)itemView.findViewById(R.id.footer_text); }else { itemTime = (TextView) itemView.findViewById(R.id.time); itemContent = (TextView) itemView.findViewById(R.id.content); } } } public interface OnFooterClickListener{ void onClick(); } }