Android RecyclerView添加上拉加载更多效果
程序员文章站
2023-12-18 18:59:46
先看一下效果
刷新的时候是这样的:
没有更多的时候是这样的:
既然有刷新的时候有两种状态就要定义两个状态
//普通布局的type...
先看一下效果
刷新的时候是这样的:
没有更多的时候是这样的:
既然有刷新的时候有两种状态就要定义两个状态
//普通布局的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); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。