欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android RecyclerView添加上拉加载更多效果

程序员文章站 2023-12-16 10:06:34
先看一下效果 刷新的时候是这样的: 没有更多的时候是这样的: 既然有刷新的时候有两种状态就要定义两个状态 //普通布局的type...

先看一下效果

Android RecyclerView添加上拉加载更多效果

刷新的时候是这样的:

Android RecyclerView添加上拉加载更多效果

没有更多的时候是这样的:

Android RecyclerView添加上拉加载更多效果

既然有刷新的时候有两种状态就要定义两个状态

//普通布局的type
static final int type_item = 0;
//脚布局
static final int type_footer = 1;

在特定的时候去显示:

 @override
  public int getitemviewtype(int position) {
    //如果position加1正好等于所有item的总和,说明是最后一个item,将它设置为脚布局
    if (position + 1 == getitemcount()) {
      return type_footer;
    } else {
      return type_item;
    }
  }

然后根据这个type来inflate不同的布局:

 @override
  public recyclerview.viewholder oncreateviewholder(viewgroup parent, int viewtype) {
    if (viewtype == type_item) {
      view view = view.inflate(mcontext, r.layout.item_recycler, null);
      myviewholder holder = new myviewholder(view);
      return holder;
    } else if (viewtype == type_footer) {
      //脚布局
      view view = view.inflate(mcontext, r.layout.recycler_load_more_layout, null);
      footviewholder footviewholder = new footviewholder(view);
      return footviewholder;
    }
    return null;
  }

以上只是控制了loading布局的出现可隐藏,还要2中状态需要控制就是上面的2个图,一个是正在加载,一个是加载完成状态,这两个状态在adapter里显然是控制不了的,必须要在请求数据的时候才能知道这两种状态,而加载数据又是在activity中执行的,所以我们需要一个用来传递状态的方法:

/**
   * 改变脚布局的状态的方法,在activity根据请求数据的状态来改变这个状态
   *
   * @param state
   */
  public void changestate(int state) {
    this.footer_state = state;
    notifydatasetchanged();
  }

用来接收状态的变量:

//上拉加载更多
// static final int pull_load_more = 0;
  //正在加载更多
  static final int loading_more = 1;
  //没有更多
  static final int no_more = 2;
  //脚布局当前的状态,默认为没有更多
  int footer_state = 1;

然后就可以根据这几种状态来控制布局控件的改变了:

 @override
  public void onbindviewholder(recyclerview.viewholder holder, int position) {
    if (holder instanceof myviewholder) {
      ((myviewholder) holder).mtextview.settext(mlist.get(position));
    } else if (holder instanceof footviewholder) {
      footviewholder footviewholder = (footviewholder) holder;
      if (position == 0) {//如果第一个就是脚布局,,那就让他隐藏
        footviewholder.mprogressbar.setvisibility(view.gone);
        footviewholder.tv_line1.setvisibility(view.gone);
        footviewholder.tv_line2.setvisibility(view.gone);
        footviewholder.tv_state.settext("");
      }
      switch (footer_state) {//根据状态来让脚布局发生改变
//        case pull_load_more://上拉加载
//          footviewholder.mprogressbar.setvisibility(view.gone);
//          footviewholder.tv_state.settext("上拉加载更多");
//          break;
        case loading_more:
          footviewholder.mprogressbar.setvisibility(view.visible);
          footviewholder.tv_line1.setvisibility(view.gone);
          footviewholder.tv_line2.setvisibility(view.gone);
          footviewholder.tv_state.settext("正在加载...");
          break;
        case no_more:
          footviewholder.mprogressbar.setvisibility(view.gone);
          footviewholder.tv_line1.setvisibility(view.visible);
          footviewholder.tv_line2.setvisibility(view.visible);
          footviewholder.tv_state.settext("我是有底线的");
          footviewholder.tv_state.settextcolor(color.parsecolor("#ff00ff"));
          break;
      }
    }
  }

不要忘了返回的count也要加1,因为添加了一个脚布局:

 @override
  public int getitemcount() {
    return mlist != null ? mlist.size() + 1 : 0;
  }

那么什么时候去传递状态到adapter呢?这里就需要给recyclerview添加滑动监听了,当他滑动到底部的时候显示加载中的状态:

//给recyclerview添加滑动监听
    mrecycler.addonscrolllistener(new recyclerview.onscrolllistener() {
      @override
      public void onscrollstatechanged(recyclerview recyclerview, int newstate) {
        super.onscrollstatechanged(recyclerview, newstate);
        /*
        到达底部了,如果不加!isloading的话到达底部如果还一滑动的话就会一直进入这个方法
        就一直去做请求网络的操作,这样的用户体验肯定不好.添加一个判断,每次滑倒底只进行一次网络请求去请求数据
        当请求完成后,在把isloading赋值为false,下次滑倒底又能进入这个方法了
         */
        if (newstate == recyclerview.scroll_state_idle && lastvisibleitem + 1 == madapter.getitemcount() && !isloading) {
          //到达底部之后如果footview的状态不是正在加载的状态,就将 他切换成正在加载的状态
          if (page < totlepage) {
            log.e("duanlian", "onscrollstatechanged: " + "进来了");
            isloading = true;
            madapter.changestate(1);
            new handler().postdelayed(new runnable() {
              @override
              public void run() {
                getdata();
                page++;
              }
            }, 2000);
          } else {
            madapter.changestate(2);

          }
        }
      }

      @override
      public void onscrolled(recyclerview recyclerview, int dx, int dy) {
        super.onscrolled(recyclerview, dx, dy);
        //拿到最后一个出现的item的位置
        lastvisibleitem = linearlayoutmanager.findlastvisibleitemposition();
      }
    });

重点就这几个,下面给出脚布局:

<?xml version="1.0" encoding="utf-8"?>
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/ll_below"
        android:layout_width="match_parent"
        android:layout_height="45dp"
  >

  <linearlayout
    android:layout_width="fill_parent"
    android:layout_height="45dp"
    android:gravity="center"
    android:orientation="horizontal">

    <textview
      android:id="@+id/tv_line1"
      android:layout_width="60dp"
      android:layout_height="1dp"
      android:layout_marginright="10dp"
      android:background="#ff00ff"
      android:visibility="gone"/>

    <progressbar
      android:id="@+id/progressbar"
      android:layout_width="25dp"
      android:layout_height="25dp"
      android:visibility="visible"/>

    <textview
      android:id="@+id/foot_view_item_tv"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginleft="4dp"
      android:text="上拉加载更多"/>

    <textview
      android:id="@+id/tv_line2"
      android:layout_width="60dp"
      android:layout_height="1dp"
      android:layout_marginleft="10dp"
      android:background="#ff00ff"
      android:visibility="gone"/>
  </linearlayout>
</relativelayout>


adapter的代码:

package com.duanlian.recyclerviewloadmoredemo;

import android.content.context;
import android.graphics.color;
import android.support.v7.widget.recyclerview;
import android.view.view;
import android.view.viewgroup;
import android.widget.progressbar;
import android.widget.textview;

import java.util.list;


public class myrecycleradapter extends recyclerview.adapter<recyclerview.viewholder> {
  private context mcontext;
  private list<string> mlist;
  //普通布局的type
  static final int type_item = 0;
  //脚布局
  static final int type_footer = 1;
  //  //上拉加载更多
//  static final int pull_load_more = 0;
  //正在加载更多
  static final int loading_more = 1;
  //没有更多
  static final int no_more = 2;
  //脚布局当前的状态,默认为没有更多
  int footer_state = 1;

  public myrecycleradapter(context context, list<string> list) {
    mcontext = context;
    mlist = list;
  }

  @override
  public recyclerview.viewholder oncreateviewholder(viewgroup parent, int viewtype) {
    if (viewtype == type_item) {
      view view = view.inflate(mcontext, r.layout.item_recycler, null);
      myviewholder holder = new myviewholder(view);
      return holder;
    } else if (viewtype == type_footer) {
      //脚布局
      view view = view.inflate(mcontext, r.layout.recycler_load_more_layout, null);
      footviewholder footviewholder = new footviewholder(view);
      return footviewholder;
    }
    return null;
  }

  @override
  public void onbindviewholder(recyclerview.viewholder holder, int position) {
    if (holder instanceof myviewholder) {
      ((myviewholder) holder).mtextview.settext(mlist.get(position));
    } else if (holder instanceof footviewholder) {
      footviewholder footviewholder = (footviewholder) holder;
      if (position == 0) {//如果第一个就是脚布局,,那就让他隐藏
        footviewholder.mprogressbar.setvisibility(view.gone);
        footviewholder.tv_line1.setvisibility(view.gone);
        footviewholder.tv_line2.setvisibility(view.gone);
        footviewholder.tv_state.settext("");
      }
      switch (footer_state) {//根据状态来让脚布局发生改变
//        case pull_load_more://上拉加载
//          footviewholder.mprogressbar.setvisibility(view.gone);
//          footviewholder.tv_state.settext("上拉加载更多");
//          break;
        case loading_more:
          footviewholder.mprogressbar.setvisibility(view.visible);
          footviewholder.tv_line1.setvisibility(view.gone);
          footviewholder.tv_line2.setvisibility(view.gone);
          footviewholder.tv_state.settext("正在加载...");
          break;
        case no_more:
          footviewholder.mprogressbar.setvisibility(view.gone);
          footviewholder.tv_line1.setvisibility(view.visible);
          footviewholder.tv_line2.setvisibility(view.visible);
          footviewholder.tv_state.settext("我是有底线的");
          footviewholder.tv_state.settextcolor(color.parsecolor("#ff00ff"));
          break;
      }
    }
  }


  @override
  public int getitemviewtype(int position) {
    //如果position加1正好等于所有item的总和,说明是最后一个item,将它设置为脚布局
    if (position + 1 == getitemcount()) {
      return type_footer;
    } else {
      return type_item;
    }
  }

  @override
  public int getitemcount() {
    return mlist != null ? mlist.size() + 1 : 0;
  }

  /**
   * 正常布局的viewholder
   */
  class myviewholder extends recyclerview.viewholder {
    textview mtextview;

    public myviewholder(view itemview) {
      super(itemview);
      mtextview = (textview) itemview.findviewbyid(r.id.item_textview);
    }
  }

  /**
   * 脚布局的viewholder
   */
  public static class footviewholder extends recyclerview.viewholder {
    private progressbar mprogressbar;
    private textview tv_state;
    private textview tv_line1;
    private textview tv_line2;


    public footviewholder(view itemview) {
      super(itemview);
      mprogressbar = (progressbar) itemview.findviewbyid(r.id.progressbar);
      tv_state = (textview) itemview.findviewbyid(r.id.foot_view_item_tv);
      tv_line1 = (textview) itemview.findviewbyid(r.id.tv_line1);
      tv_line2 = (textview) itemview.findviewbyid(r.id.tv_line2);

    }
  }

  /**
   * 改变脚布局的状态的方法,在activity根据请求数据的状态来改变这个状态
   *
   * @param state
   */
  public void changestate(int state) {
    this.footer_state = state;
    notifydatasetchanged();
  }

}

activity中的代码:

package com.duanlian.recyclerviewloadmoredemo;

import android.os.bundle;
import android.os.handler;
import android.support.v7.app.appcompatactivity;
import android.support.v7.widget.linearlayoutmanager;
import android.support.v7.widget.recyclerview;
import android.util.log;

import java.util.arraylist;
import java.util.list;

public class mainactivity extends appcompatactivity {

  private recyclerview mrecycler;
  private list<string> mlist;
  private list<string> list;
  private myrecycleradapter madapter;
  linearlayoutmanager linearlayoutmanager;
  int lastvisibleitem;
  int page = 0;
  boolean isloading = false;//用来控制进入getdata()的次数
  int totlepage = 5;//模拟请求的一共的页数

  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
    initview();
    getdata();
  }

  private void initview() {
    mrecycler = (recyclerview) findviewbyid(r.id.recycler);
    linearlayoutmanager = new linearlayoutmanager(this);
    mrecycler.setlayoutmanager(linearlayoutmanager);
    mlist = new arraylist<>();
    madapter = new myrecycleradapter(this, mlist);
    mrecycler.setadapter(madapter);
    //给recyclerview添加滑动监听
    mrecycler.addonscrolllistener(new recyclerview.onscrolllistener() {
      @override
      public void onscrollstatechanged(recyclerview recyclerview, int newstate) {
        super.onscrollstatechanged(recyclerview, newstate);
        /*
        到达底部了,如果不加!isloading的话到达底部如果还一滑动的话就会一直进入这个方法
        就一直去做请求网络的操作,这样的用户体验肯定不好.添加一个判断,每次滑倒底只进行一次网络请求去请求数据
        当请求完成后,在把isloading赋值为false,下次滑倒底又能进入这个方法了
         */
        if (newstate == recyclerview.scroll_state_idle && lastvisibleitem + 1 == madapter.getitemcount() && !isloading) {
          //到达底部之后如果footview的状态不是正在加载的状态,就将 他切换成正在加载的状态
          if (page < totlepage) {
            log.e("duanlian", "onscrollstatechanged: " + "进来了");
            isloading = true;
            madapter.changestate(1);
            new handler().postdelayed(new runnable() {
              @override
              public void run() {
                getdata();
                page++;
              }
            }, 2000);
          } else {
            madapter.changestate(2);

          }
        }
      }

      @override
      public void onscrolled(recyclerview recyclerview, int dx, int dy) {
        super.onscrolled(recyclerview, dx, dy);
        //拿到最后一个出现的item的位置
        lastvisibleitem = linearlayoutmanager.findlastvisibleitemposition();
      }
    });

  }

  /**
   * 模拟请求数据
   */
  private void getdata() {
    list = new arraylist<>();
    for (int i = 0; i < 10; i++) {
      list.add("第" + i + "条");
    }
    mlist.addall(list);
    isloading = false;
    madapter = new myrecycleradapter(this, mlist);
    mrecycler.setadapter(madapter);
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: