Android RecyclerView自定义上拉和下拉刷新效果
程序员文章站
2024-02-11 21:04:46
使用recyclerview越来越多了,基本可以不用listview了,但是这个新的控件谷歌官方似乎设计的没有想listview那样方便快捷,listview自带有head...
使用recyclerview越来越多了,基本可以不用listview了,但是这个新的控件谷歌官方似乎设计的没有想listview那样方便快捷,listview自带有headview和 footerview所有我们很方便的可以实现上拉,下拉刷新,但是我们使用recyclerview就没有那样的舒服了,需要自己动手来实现这两个模块了。
本人参考了其他几篇博客使用了下感觉都有bug存在,于是自己改进了下,基本实现了功能,由于时间原因代码封装的还不彻底,仅供参考。
首页布局:activity_notice
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.coordinatorlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:orientation="vertical" > <include layout="@layout/toolbar" /> <android.support.v4.widget.swiperefreshlayout android:id="@+id/swiperefreshlayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.recyclerview android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"></android.support.v7.widget.recyclerview> </android.support.v4.widget.swiperefreshlayout> </android.support.design.widget.coordinatorlayout>
子item布局:item_base
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.cardview xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginleft="@dimen/margin_10" android:layout_marginright="@dimen/margin_10" android:layout_margintop="6dp" android:orientation="vertical" app:cardbackgroundcolor="@color/line" app:cardpreventcorneroverlap="true" app:cardusecompatpadding="true" app:contentpadding="6dp"> <linearlayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <textview android:id="@+id/tv_date" style="@style/normaltextview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2016-10-9 10:00" /> <android.support.v7.widget.cardview android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:cardbackgroundcolor="@color/white" app:cardpreventcorneroverlap="true" app:cardusecompatpadding="true" app:contentpadding="10dp"> <textview android:id="@+id/tv_title" style="@style/smallgreytextview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="end" android:maxlines="2" android:text="。。。,看到这个场景。我看着她她看着我,说道:“怎么样,我当年的手工还不错吧。。。。。。。。。”" /> </android.support.v7.widget.cardview> </linearlayout> </android.support.v7.widget.cardview>
脚布局 item_foot
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="40dp" android:gravity="center" android:orientation="horizontal" android:id="@+id/ll" > <progressbar android:layout_marginright="6dp" android:id="@+id/progressbar" style="?android:attr/progressbarstylesmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> <textview android:id="@+id/tv" style="@style/smallgreytextview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/loading" /> </linearlayout>
toolbar
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <android.support.design.widget.appbarlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:fitssystemwindows="true"> <android.support.v7.widget.toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/bluestatus" android:minheight="?attr/actionbarsize" app:layout_scrollflags="scroll|enteralways" app:navigationicon="?attr/homeasupindicator" app:theme="@style/theme.appcompat.noactionbar"> </android.support.v7.widget.toolbar> </android.support.design.widget.appbarlayout>
首页 mainactivity
package com.lxl.refresh; import android.os.bundle; import android.os.handler; import android.support.v4.widget.swiperefreshlayout; import android.support.v7.app.appcompatactivity; import android.support.v7.widget.linearlayoutmanager; import android.support.v7.widget.recyclerview; import android.support.v7.widget.toolbar; import android.util.log; import android.view.view; import java.util.arraylist; import java.util.hashmap; import java.util.list; import java.util.map; import butterknife.butterknife; import butterknife.injectview; /** * description: * author:lxl * date: 2016/10/9 10:15 */ public class mainactivity extends appcompatactivity { @injectview(r.id.toolbar) toolbar toolbar; @injectview(r.id.recyclerview) recyclerview recyclerview; @injectview(r.id.swiperefreshlayout) swiperefreshlayout swiperefreshlayout; boolean isslidingtolast = false; //判断滚动状态 boolean isloading; private list<map<string, object>> data = new arraylist<>(); private recyclerviewadapter adapter = new recyclerviewadapter(this, data); private handler handler = new handler(); @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_notice); butterknife.inject(this); initview(); map<string, object> map = new hashmap<>(); initdata(); } public void initview() { setsupportactionbar(toolbar); toolbar.settitle(r.string.notice); toolbar.setnavigationonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { finish(); } }); swiperefreshlayout.setcolorschemeresources(r.color.bluestatus); swiperefreshlayout.post(new runnable() { @override public void run() { swiperefreshlayout.setrefreshing(true); } }); swiperefreshlayout.setonrefreshlistener(new swiperefreshlayout.onrefreshlistener() { @override public void onrefresh() { handler.postdelayed(new runnable() { @override public void run() { data.clear(); getdata(); } }, 2000); } }); final linearlayoutmanager layoutmanager = new linearlayoutmanager(this); recyclerview.setlayoutmanager(layoutmanager); recyclerview.setadapter(adapter); recyclerview.addonscrolllistener(new recyclerview.onscrolllistener() { @override public void onscrollstatechanged(recyclerview recyclerview, int newstate) { super.onscrollstatechanged(recyclerview, newstate); log.d("test", "statechanged = " + newstate); //滑动状态改变时触发有0,1,2三种状态 } @override public void onscrolled(recyclerview recyclerview, int dx, int dy) { super.onscrolled(recyclerview, dx, dy); if (dy > 0) { //大于0表示正在向下滚动 isslidingtolast = true; } else { //小于等于0表示停止或向上滚动 isslidingtolast = false; } log.d("test", "onscrolled"); //当recyclerview滑动时触发类似点击事件的motionevent.action_move int lastvisibleitemposition = layoutmanager.findlastvisibleitemposition(); if (lastvisibleitemposition + 1 == adapter.getitemcount()&& isslidingtolast) { log.d("test", "loading executed");//当且仅当滑动到最后一项并且手指上拉抛出时才执行 boolean isrefreshing = swiperefreshlayout.isrefreshing(); log.d("test", "hahh"+isrefreshing); if (isrefreshing) { //如何在下拉刷新则隐藏脚布局并且返回 adapter.notifyitemremoved(adapter.getitemcount()); return; } if (!isloading) { isloading = true; handler.postdelayed(new runnable() { @override public void run() { getdata(); //延时执行加载 log.d("test", "load more completed"); isloading = false; } }, 1000); } } } }); //添加点击事件 adapter.setonitemclicklistener(new recyclerviewadapter.onitemclicklistener() { @override public void onitemclick(view view, int position) { log.d("test", "item position = " + position); } @override public void onitemlongclick(view view, int position) { } }); } public void initdata() { //第一次进来的时候加载数据 handler.postdelayed(new runnable() { @override public void run() { getdata(); } }, 1500); } /** * 获取测试数据 */ private void getdata() { for (int i = 0; i < 6; i++) { //每次加载六条数据 map<string, object> map = new hashmap<>(); data.add(map); } adapter.notifydatasetchanged(); swiperefreshlayout.setrefreshing(false); //加载数据后收起下拉刷新 log.d("test", adapter.getitemcount()+""); // adapter.notifyitemremoved(adapter.getitemcount()); //加载数据后上拉刷新的脚布局移除掉 // adapter.footerholder.ll.setvisibility(view.gone); //加载数据后上拉刷新的脚布局隐藏掉 adapter.setmcreateviewholder(new recyclerviewadapter.onholdercreate() { @override public void created() { if (isslidingtolast==false){ adapter.footerholder.ll.setvisibility(view.gone); }else{ adapter.footerholder.ll.setvisibility(view.visible); } } }); } }
在第106行中通过这三个条件判断就可以下拉刷新的执行。
recyclerview的适配器:recyclerviewadapter
package com.lxl.refresh; import android.content.context; import android.support.v7.widget.recyclerview.adapter; import android.support.v7.widget.recyclerview.viewholder; import android.util.log; import android.view.layoutinflater; import android.view.view; import android.view.viewgroup; import android.widget.linearlayout; import android.widget.progressbar; import android.widget.textview; import java.util.list; public class recyclerviewadapter extends adapter<viewholder> { private static final int type_item = 0; private static final int type_footer = 1; private context context; private list data; protected footviewholder footerholder; public recyclerviewadapter(context context, list data) { this.context = context; this.data = data; } //------------------------------------- public interface onholdercreate{ //定义一个viewholder回调接口 void created(); } public onholdercreate getmcreateviewholder() { return mcreateviewholder; } public void setmcreateviewholder(onholdercreate mcreateviewholder) { this.mcreateviewholder = mcreateviewholder; } private onholdercreate mcreateviewholder; //------------------------------------- public interface onitemclicklistener { void onitemclick(view view, int position); void onitemlongclick(view view, int position); } private onitemclicklistener onitemclicklistener; public void setonitemclicklistener(onitemclicklistener onitemclicklistener) { this.onitemclicklistener = onitemclicklistener; } @override public int getitemcount() { return data.size() == 0 ? 0 : data.size() + 1; //添加脚布局 } @override public int getitemviewtype(int position) { if (position + 1 == getitemcount()) { return type_footer; //脚布局 } else { return type_item; //普通item } } @override public viewholder oncreateviewholder(viewgroup parent, int viewtype) { if (viewtype == type_item) { //创建普通类型的item布局 view view = layoutinflater.from(context).inflate(r.layout.item_base, parent, false); log.d("test", "创建普通类型的item布局"); return new itemviewholder(view); } else if (viewtype == type_footer) { //创建脚布局类型的item布局 view view = layoutinflater.from(context).inflate(r.layout.item_foot, parent, false); footerholder=new footviewholder(view); log.d("test", "创建脚布局类型的item布局"); return footerholder; } return null; } @override public void onbindviewholder(final viewholder holder, int position) { //在oncreateviewholder执行完成后回调 if (holder instanceof footviewholder){ if (mcreateviewholder!=null){ mcreateviewholder.created(); } } if (holder instanceof itemviewholder) { //holder.tv.settext(data.get(position)); if (onitemclicklistener != null) { holder.itemview.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { int position = holder.getlayoutposition(); onitemclicklistener.onitemclick(holder.itemview, position); } }); holder.itemview.setonlongclicklistener(new view.onlongclicklistener() { @override public boolean onlongclick(view v) { int position = holder.getlayoutposition(); onitemclicklistener.onitemlongclick(holder.itemview, position); return false; } }); } } } static class itemviewholder extends viewholder { textview tv; public itemviewholder(view view) { super(view); tv = (textview) view.findviewbyid(r.id.tv_date); } } class footviewholder extends viewholder { linearlayout ll; progressbar pb; textview tv; public footviewholder(view view) { super(view); ll=(linearlayout) view.findviewbyid(r.id.ll); pb=(progressbar) view.findviewbyid(r.id.progressbar); tv=(textview) view.findviewbyid(r.id.tv); } } }
在第30行定义一个借口用来通知下拉刷新后隐藏脚布局,主要在oncreateviewholder执行完成后回调。
看看效果图
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
Android RecyclerView自定义上拉和下拉刷新效果
-
Android第三方PullToRefresh实现下拉刷新上拉加载使用教程。。。
-
Diycode开源项目实例搭建上拉加载和下拉刷新的Fragment
-
在React中使用Native如何实现自定义下拉刷新上拉加载的列表
-
Android下拉刷新上拉加载更多左滑动删除
-
Android RecyclerView上拉加载和下拉刷新
-
Android RecyclerView上拉加载和下拉刷新(基础版)
-
ios基于MJRefresh实现上拉刷新和下拉加载动画效果
-
Android实现上拉加载更多以及下拉刷新功能(ListView)
-
Android RecyclerView实现下拉刷新和上拉加载更多