实现原理是使用recyclerview的ontouchlistener方法监听滑动 在adapter里面增加两项footview 其中date.size为显示的加载条,可以自定义,date.size+1为空白的view,我们设置其高度为0 我们通过linearlayoutmanager的 findlastvisibleitemposition判断显示的最后一条数据,如果是空白view,表示加载条已经完全展示,松开即可刷新。
回弹效果是通过在滑动时动态改变空白view的高度,达到阻尼效果 ,回弹时再动态将其改为0,达到回弹效果,通过loading防止加载过程中滑动导致显示问题 这里的回调采用了runnable传参
public class refreshfootadapter extends recyclerview.adapter<recyclerview.viewholder> { // 上拉加载更多 public static final int satus_pullup_load_more = 0; // 正在加载中 public static final int satus_loading_more = 1; public static final int satus_up_loading_more = 2; // 上拉加载更多状态-默认为0 private int load_more_status = 0; private layoutinflater minflater; private list<string> mtitles = null; private static final int type_item = 0; // 普通item view private static final int type_footer = 1; // 底部footview private static final int type_footer_empty = 2; // 底部空白view private static int pagesize; private int eview_height = 1; private long timeflag;// 回弹时间 private recyclerview parent; private boolean loadmare;// 判断当前是可加载更多 private boolean loading;// 判断是否正在加载 private int starty, nowy;// 滑动判断 <span style="white-space:pre"> </span>//构造函数 处理滑动监听 更新等功能 public refreshfootadapter(context context, recyclerview parent, final linearlayoutmanager linearlayoutmanager, int pagesize, final runnable onloadmore) { this.parent = parent; this.minflater = layoutinflater.from(context); this.mtitles = new arraylist<string>(); for (int i = 0; i < 20; i++) { int index = i + 1; mtitles.add("item" + index); } this.pagesize = pagesize; parent.setontouchlistener(new ontouchlistener() { @override public boolean ontouch(view v, motionevent ev) { // todo auto-generated method stub switch (ev.getaction()) { case motionevent.action_move: nowy = (int) ev.gety(); if (refreshfootadapter.this.getitemcount() == linearlayoutmanager .findlastvisibleitemposition() + 1) { if (starty == 0) {// 按下 starty = nowy; } int changey = nowy - starty; refreshfootadapter.this .notifyemptyview((int) (-changey / 1.3f)); if (loading) { return false; } refreshfootadapter.this .changemorestatus(refreshfootadapter.this.satus_up_loading_more); loadmare = true; } else { loadmare = false; if (loading) { return false; } refreshfootadapter.this .changemorestatus(refreshfootadapter.this.satus_pullup_load_more); // 普通的滑动 starty = 0; } break; case motionevent.action_up: refreshfootadapter.this.resetemptyview(); if (loadmare) { if (loading) { return false; } else { refreshfootadapter.this .changemorestatus(refreshfootadapter.this.satus_loading_more); if (onloadmore != null && !loading) { loading = true; onloadmore.run(); } } } starty = 0; break; default: break; } return false; } }); } /** * item显示类型 * * @param parent * @param viewtype * @return */ public recyclerview.viewholder oncreateviewholder(viewgroup parent, int viewtype) { // 进行判断显示类型,来创建返回不同的view if (viewtype == type_item) { view view = minflater.inflate(r.layout.item_recycler_layout, parent, false); // 这边可以做一些属性设置,甚至事件监听绑定 // view.setbackgroundcolor(color.red); itemviewholder itemviewholder = new itemviewholder(view); return itemviewholder; } else if (viewtype == type_footer) { view foot_view = minflater.inflate( r.layout.recycler_load_more_layout, parent, false); // 这边可以做一些属性设置,甚至事件监听绑定 // view.setbackgroundcolor(color.red); footviewholder footviewholder = new footviewholder(foot_view); return footviewholder; } else if (viewtype == type_footer_empty) { view foot_view_empty = minflater.inflate( r.layout.recycler_load_more_layout_empty, parent, false); // 这边可以做一些属性设置,甚至事件监听绑定 // view.setbackgroundcolor(color.red); footemptyholder footemptyviewholder = new footemptyholder( foot_view_empty); return footemptyviewholder; } return null; } /** * 数据的绑定显示 * * @param holder * @param position */ public void onbindviewholder(recyclerview.viewholder holder, int position) { if (holder instanceof itemviewholder) { ((itemviewholder) holder).item_tv.settext(mtitles.get(position)); holder.itemview.settag(position); } else if (holder instanceof footviewholder) { footviewholder footviewholder = (footviewholder) holder; switch (load_more_status) { case satus_pullup_load_more: footviewholder.foot_view_item_tv.settext("上拉加载更多..."); break; case satus_loading_more: footviewholder.foot_view_item_tv.settext("正在加载更多数据..."); break; case satus_up_loading_more: footviewholder.foot_view_item_tv.settext("松开加载更多数据..."); break; } } else if (holder instanceof footemptyholder) { footemptyholder footviewholder = (footemptyholder) holder; footviewholder.empty.setlayoutparams(new viewgroup.layoutparams( 111, eview_height)); } } /** * 进行判断是普通item视图还是footview视图 * * @param position * @return */ @override public int getitemviewtype(int position) { // 最后一个item设置为footerview if (position + 1 == getitemcount()) { return type_footer_empty; } else if (position + 2 == getitemcount()) { return type_footer; } else { return type_item; } } <span style="white-space:pre"> </span>//如果是页数的倍数 itemcount+2 @override public int getitemcount() { if (mtitles.size() % pagesize != 0) { return mtitles.size(); } else { return mtitles.size() + 2; } // return mtitles.size()+1; } // 自定义的viewholder,持有每个item的的所有界面元素 public static class itemviewholder extends recyclerview.viewholder { public textview item_tv; public itemviewholder(view view) { super(view); item_tv = (textview) view.findviewbyid(r.id.item_tv); } } /** * 底部footview布局 */ public static class footviewholder extends recyclerview.viewholder { private textview foot_view_item_tv; public footviewholder(view view) { super(view); foot_view_item_tv = (textview) view .findviewbyid(r.id.foot_view_item_tv); } } <span style="white-space:pre"> </span>//空白项 public static class footemptyholder extends recyclerview.viewholder { private view empty; public footemptyholder(view view) { super(view); empty = view.findviewbyid(r.id.empty); } } // 添加数据 public void additem(list<string> newdatas) { // mtitles.add(position, data); // notifyiteminserted(position); newdatas.addall(mtitles); mtitles.removeall(mtitles); mtitles.addall(newdatas); notifydatasetchanged(); } <span style="white-space:pre"> </span>//更新添加数据 public void addmoreitem(list<string> newdatas) { mtitles.addall(newdatas); notifydatasetchanged(); } <span style="white-space:pre"> </span>//更新空白项高度 private void notifyemptyview(int height) { this.eview_height = height; notifyitemchanged(getitemcount() - 1); } <span style="white-space:pre"> </span>//空白回弹 伪回弹动画 private void resetemptyview() { final int dx = eview_height; new thread(new runnable() { @override public void run() { // todo auto-generated method stub final int time = 500; final long starttime = new date().gettime(); timeflag = starttime; long nowtime = new date().gettime(); while (starttime + time > nowtime && timeflag == starttime) { nowtime = new date().gettime(); final int dt = (int) (nowtime - starttime); parent.post(new runnable() { @override public void run() { // todo auto-generated method stub eview_height = eview_height * (time - dt) / time; notifydatasetchanged(); } }); try { thread.sleep(10); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } } parent.post(new runnable() { @override public void run() { // todo auto-generated method stub eview_height = 0; notifydatasetchanged(); } }); } }).start(); } <span style="white-space:pre"> </span>//停止加载更多 重置loading状态和显示文本 public void stoploadmore() { notifydatasetchanged(); loading = false; refreshfootadapter.this .changemorestatus(refreshfootadapter.this.satus_pullup_load_more); } //改变加载条状态 private void changemorestatus(int status) { if (loading) { return; } load_more_status = status; notifydatasetchanged(); } }
图1为滑动过程
图2为松开加载
以上所述是小编给大家介绍的android recyclerview上拉加载更多功能回弹实现代码,希望对大家有所帮助
如对本文有疑问, 点击进行留言回复!!
Codeforces C. A Cookie for You (模拟 / 分类 / 贪心) (Round #654 Div.2)
DialogFragment弹窗(带黑色透明背景和不带黑色透明背景)
网友评论