程序员

RecyclerView多层嵌套列表的实现,加下拉刷新上拉加载。

2020-12-14  本文已影响0人  永远爱你ol

RecyclerView是安卓中比较常用的列表控件了,当然刚接触这个控件的时候肯定也会遇到很多问题。接下来分享一下自己遇到的问题和解决方法。


20201214-135552.png

像上图这种列表就需要双层嵌套了,接下来我们先创建RecyclerView控件。

 RecyclerView ListView = (RecyclerView)findViewById(R.id.adapter_list);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        ListView.setLayoutManager(layoutManager);
        ListView.addItemDecoration(new SpacesItemDecoration(14));
        adapter = new JiankangpersonAdapter(DActivity.this,heathList);
        ListView.setAdapter(adapter);
        appRefresh();//下拉刷新
        EndLessOnScrollListener.reSet(); //上拉加载
          ListView.addOnScrollListener(new EndLessOnScrollListener(layoutManager) {
            @Override
            public void onLoadMore(int currentPage) {
               //需要加载的数据
            }
          });

附上对应的adapt的代码,其中包括了实现上拉加载的功能。

public class JiankangpersonAdapter extends  RecyclerView.Adapter<RecyclerView.ViewHolder>{
    private List<HeathpersonUserinfo> mDatas;
    private Context context;
    private int normalType = 0;     // 第一种ViewType,正常的item
    private int footType = 1;       // 第二种ViewType,底部的提示View
    private boolean fadeTips = false; // 变量,是否隐藏了底部的提示
    public JiankangpersonAdapter(Context context, List<HeathpersonUserinfo> data){
        mDatas = data;
        this.context = context;
    }

  class NormalHolder extends RecyclerView.ViewHolder {
    public TextView date;
    public RecyclerView persondetailList;

    public NormalHolder(View v) {
      super(v);
      date=(TextView)v.findViewById(R.id.person_date);
      persondetailList = (RecyclerView)v.findViewById(R.id.jiankangpersoninfo_list);
    }
  }

  class FootHolder extends RecyclerView.ViewHolder {
    private TextView tips;

    public FootHolder(View itemView) {
      super(itemView);
      tips = (TextView) itemView.findViewById(R.id.tips);
    }
  }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      if (viewType == normalType) {
        NormalHolder normalHolder =new NormalHolder (LayoutInflater.from(parent.getContext()).inflate(R.layout.view_jiankangperson, parent, false));
        return normalHolder;
      }else{
        return new FootHolder(LayoutInflater.from(context).inflate(R.layout.foot_item, null));
      }
    }
    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
      if (holder instanceof  NormalHolder) {
        HeathpersonUserinfo huser = mDatas.get(position);
        ((NormalHolder)holder).date.setText(huser.getDate());
        ((NormalHolder)holder).date.setTextColor(Color.parseColor("#557ac4"));
        holder.itemView.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
            //Toast.makeText(context, "点击了", Toast.LENGTH_SHORT).show();
          }
        });
        ((NormalHolder)holder).persondetailList.setLayoutManager(new LinearLayoutManager(context));
        //holder.persondetailList.addItemDecoration(new SpacesItemDecoration(4));
        final JiankangpersonInfoAdapter checkinfoAdapter = new JiankangpersonInfoAdapter(context,huser.getPersondetail());
        ((NormalHolder)holder).persondetailList.setAdapter(checkinfoAdapter);
      }else{
        ((JiankangpersonAdapter.FootHolder) holder).tips.setVisibility(View.VISIBLE);
        if (EndLessOnScrollListener.isHasMore() == false) {
          fadeTips = false;
          if (mDatas.size() > 0) {
            ((JiankangpersonAdapter.FootHolder) holder).tips.setText("正在加载更多...");
          }
        } else {
          if (mDatas.size() > 0) {
            ((JiankangpersonAdapter.FootHolder) holder).tips.setText("没有更多数据了");
          }else {
            ((JiankangpersonAdapter.FootHolder) holder).tips.setVisibility(View.GONE);
          }
        }
      }
    }

    @Override
    public int getItemCount() {
        return mDatas.size()+1;
    }

  @Override
  public int getItemViewType(int position) {
    if (position == getItemCount() - 1) {
      return footType;
    } else {
      return normalType;
    }
  }
}

最关键的是这一部分,在最后加上这段代码,就可以实现在当前列表循环之下,再嵌套一层循环。

 ((NormalHolder)holder).persondetailList.setLayoutManager(new LinearLayoutManager(context));
 final JiankangpersonInfoAdapter checkinfoAdapter = new JiankangpersonInfoAdapter(context,huser.getPersondetail());
  ((NormalHolder)holder).persondetailList.setAdapter(checkinfoAdapter);

因为JiankangpersonInfoAdapter中不需要添加上拉加载的功能,所以adapter的结构是有所区别的(结构示例如下)。

public class JiankangpersonInfoAdapter extends  RecyclerView.Adapter<JiankangpersonInfoAdapter.VH>{
  static class VH extends RecyclerView.ViewHolder{

    public TextView type1;
    public TextView typekuohao;
    public VH(View v) {
      super(v);
      type1=(TextView)v.findViewById(R.id.jiankang_info_type);
      typekuohao=(TextView)v.findViewById(R.id.jiankang_info_typekuohao);
    }
  }

  private List<CheckInfo> mDatas;
  private Context context;

  public JiankangpersonInfoAdapter(Context context, List<CheckInfo> data){
    mDatas = data;
    this.context = context;
  }

  @NonNull
  @Override
  public JiankangpersonInfoAdapter.VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_jiankangperson_info, parent, false);
    final JiankangpersonInfoAdapter.VH holder = new JiankangpersonInfoAdapter.VH(v);

    return holder;
  }
  @Override
  public void onBindViewHolder(@NonNull VH holder, int position) {
      holder.type1.setText("起床");
      holder.typekuohao.setText("(生活)");
      holder.itemView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        //Toast.makeText(context, "点击了详情", Toast.LENGTH_SHORT).show();
      }
    });
  }
  public List<HeathpersonRecorddetail> initData(String recordId){
    List<HeathpersonRecorddetail> heathList = new ArrayList<HeathpersonRecorddetail>();
    return heathList;
  }

  @Override
  public int getItemCount() {
    return mDatas.size();
  }

  //  删除数据
  public void removeData(int position) {
    mDatas.remove(position);
    //删除动画
    notifyItemRemoved(position);
    notifyDataSetChanged();
  }
  //dp转px
  public static int dip2px(Context context, float dpValue) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dpValue * scale + 0.5f);
  }
}

下拉刷新首先添加如下代码。

 private SwipeRefreshLayout swipeRefreshLayout;
    Handler handlerForRefresh = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      switch (msg.what) {
        case 0x93: {
          swipeRefreshLayout.setRefreshing(false);
        }
      }
    }
  };

然后是appRefresh()方法。

private void appRefresh(){
    swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
    swipeRefreshLayout.setColorSchemeResources(R.color.blue);
    swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
      @Override
      public void onRefresh() {
        new Thread(){
          @Override
          public void run () {
            super.run();
            //同步加载网络数据
            //加载数据 完毕后 关闭刷新状态 切回主线程
            handlerForRefresh.postDelayed(new Runnable() {
              @Override
              public void run() {
               //需要刷新的数据

                EndLessOnScrollListener.reSet();//重置上拉加载的设置
                // 通知结束下拉刷新
                handlerForRefresh.sendEmptyMessage(0x93);
              }
            }, 100);
          }
        }.start();
      }
    });
  }

其中swipe_refresh_layout是需要在xml文件中添加的。

 <android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/swipe_refresh_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
  <android.support.v7.widget.RecyclerView
        android:id="@+id/jiankang_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</android.support.v4.widget.SwipeRefreshLayout>

上拉加载中关键的类 EndLessOnScrollListener。

public abstract class EndLessOnScrollListener extends  RecyclerView.OnScrollListener{

  //声明一个LinearLayoutManager
  private LinearLayoutManager mLinearLayoutManager;

  //当前页,从0开始
  private static int currentPage = 1;
  //已经加载出来的Item的数量
  private static int totalItemCount;

  //主要用来存储上一个totalItemCount
  private static int previousTotal;

  //在屏幕上可见的item数量
  private static int visibleItemCount;

  //在屏幕可见的Item中的第一个
  private static int firstVisibleItem;

  //是否正在上拉数据
  private static boolean loading = true;

  private static boolean  hasMore=true;

  private int recordFlag=0;

  public EndLessOnScrollListener(LinearLayoutManager linearLayoutManager) {
    this.mLinearLayoutManager = linearLayoutManager;
  }

  @Override
  public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    visibleItemCount = recyclerView.getChildCount();
    totalItemCount = mLinearLayoutManager.getItemCount();
    firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();
    if(recordFlag!=0){
      if(loading){
        if(totalItemCount > previousTotal){
          //说明数据已经加载结束
          hasMore=false;
          loading = false;
          previousTotal = totalItemCount;
        }
      }
      if (!loading && totalItemCount-visibleItemCount <= firstVisibleItem){
        hasMore=true;
        currentPage ++;
        onLoadMore(currentPage);
        loading = true;
      }
    }
      recordFlag++;
  }

  public  static void reSet(){
    currentPage=1;
    totalItemCount=0;
    previousTotal=0;
    visibleItemCount=0;
    firstVisibleItem=0;
    loading=true;
    hasMore=true;
  }

  public static boolean isHasMore() {
    return hasMore;
  }
  /**
   * 提供一个抽闲方法,在Activity中监听到这个EndLessOnScrollListener
   * 并且实现这个方法
   * */
  public abstract void onLoadMore(int currentPage);}

注:其中关于页面的xml文件在这边全部省略了。

上一篇下一篇

猜你喜欢

热点阅读