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

GridView基于pulltorefresh实现下拉刷新 上拉加载更多功能(推荐)

程序员文章站 2024-03-01 23:58:10
原理和listview一样 ,都是重写android原生控件 activity package com.example.refreshgridview; i...

原理和listview一样 ,都是重写android原生控件

activity

package com.example.refreshgridview; 
import java.util.arraylist; 
import java.util.list; 
import android.app.activity; 
import android.os.bundle; 
import android.widget.gridview; 
import android.widget.toast; 
import com.example.refreshgridview.pulltorefreshbase.onrefreshlistener; 
public class mainactivity extends activity { 
private pulltorefreshgridview mpullrefreshgridview; 
private gridview mgridview; 
private gridviewadapter adapter; 
@override 
protected void oncreate(bundle savedinstancestate) { 
super.oncreate(savedinstancestate); 
setcontentview(r.layout.activity_main); 
mpullrefreshgridview = (pulltorefreshgridview) findviewbyid(r.id.video_gridview); 
mpullrefreshgridview.init(pulltorefreshgridview.mode_both); 
mgridview = mpullrefreshgridview.getrefreshableview(); 
mpullrefreshgridview.setonrefreshlistener(refreshlistener); 
list<string> list = new arraylist<string>(); 
for (int i = 0; i < 40; i++) { 
list.add(i+""); 
} 
adapter = new gridviewadapter(mainactivity.this,list); 
mgridview.setadapter(adapter); 
} 
private onrefreshlistener refreshlistener = new onrefreshlistener() { 
@override 
public void onrefresh(int mode) { 
if (pulltorefreshgridview.mode_pull_down_to_refresh == mpullrefreshgridview.getcurrentmode()) { 
toast.maketext(mainactivity.this, "下拉刷新", toast.length_short).show(); 
mpullrefreshgridview.onrefreshcomplete(); 
} else if (mode == pulltorefreshgridview.mode_pull_up_to_refresh) { 
// 加载更多 
toast.maketext(mainactivity.this, "上拉加载更多", toast.length_short).show(); 
mpullrefreshgridview.onrefreshcomplete(); 
} 
} 
}; 
}

adapter

package com.example.refreshgridview; 
import java.util.arraylist; 
import java.util.list; 
import android.content.context; 
import android.content.intent; 
import android.text.textutils; 
import android.view.layoutinflater; 
import android.view.view; 
import android.view.viewgroup; 
import android.widget.baseadapter; 
import android.widget.textview; 
public class gridviewadapter extends baseadapter { 
private list<string> mlist = new arraylist<string>(); 
private context mcontext; 
public gridviewadapter(context context,list<string> list) { 
super(); 
this.mcontext = context; 
this.mlist = list; 
} 
@override 
public int getcount() { 
return mlist.size(); 
} 
@override 
public string getitem(int position) { 
return mlist.get(position); 
} 
@override 
public long getitemid(int position) { 
return position; 
} 
@override 
public view getview(int position, view convertview, viewgroup parent) { 
childholderone holder; 
if (convertview == null) { 
convertview = layoutinflater.from(mcontext).inflate(r.layout.item_grid_live_show, parent, false); 
holder = new childholderone(); 
holder.tvtitle = (textview)convertview.findviewbyid(r.id.title_tv); 
convertview.settag(holder); 
} else { 
holder = (childholderone) convertview.gettag(); 
} 
return convertview; 
} 
class childholderone { 
textview tvtitle; 
} 
}

pulltorefreshgridview

package com.example.refreshgridview; 
import android.content.context; 
import android.util.attributeset; 
import android.view.contextmenu.contextmenuinfo; 
import android.view.view; 
import android.widget.gridview; 
public class pulltorefreshgridview extends pulltorefreshadapterviewbase<gridview> { 
class internalgridview extends gridview implements emptyviewmethodaccessor { 
public internalgridview(context context, attributeset attrs) { 
super(context, attrs); 
} 
@override 
public void setemptyview(view emptyview) { 
pulltorefreshgridview.this.setemptyview(emptyview); 
} 
@override 
public void setemptyviewinternal(view emptyview) { 
super.setemptyview(emptyview); 
} 
@override 
public contextmenuinfo getcontextmenuinfo() { 
return super.getcontextmenuinfo(); 
} 
} 
public pulltorefreshgridview(context context) { 
super(context); 
} 
public pulltorefreshgridview(context context, int mode) { 
super(context, mode); 
} 
public pulltorefreshgridview(context context, attributeset attrs) { 
super(context, attrs); 
} 
@override 
protected final gridview createrefreshableview(context context, attributeset attrs) { 
gridview gv = new internalgridview(context, attrs); 
// use generated id (from res/values/ids.xml) 
gv.setid(r.id.gridview); 
return gv; 
} 
@override 
public contextmenuinfo getcontextmenuinfo() { 
return ((internalgridview) getrefreshableview()).getcontextmenuinfo(); 
} 
}

pulltorefreshbase

package com.example.refreshgridview; 
import android.content.context; 
import android.os.handler; 
import android.util.attributeset; 
import android.view.motionevent; 
import android.view.view; 
import android.view.viewconfiguration; 
import android.view.viewgroup; 
import android.view.animation.acceleratedecelerateinterpolator; 
import android.view.animation.interpolator; 
import android.widget.linearlayout; 
import android.widget.textview; 
/** 
* 
* @author zlw 
*/ 
public abstract class pulltorefreshbase<t extends view> extends linearlayout { 
final class smoothscrollrunnable implements runnable { 
static final int animation_duration_ms = 190; 
static final int animation_fps = 1000 / 60; 
private final interpolator interpolator; 
private final int scrolltoy; 
private final int scrollfromy; 
private final handler handler; 
private boolean continuerunning = true; 
private long starttime = -1; 
private int currenty = -1; 
public smoothscrollrunnable(handler handler, int fromy, int toy) { 
this.handler = handler; 
this.scrollfromy = fromy; 
this.scrolltoy = toy; 
this.interpolator = new acceleratedecelerateinterpolator(); 
} 
@override 
public void run() { 
/** 
* only set starttime if this is the first time we're starting, else 
* actually calculate the y delta 
*/ 
if (starttime == -1) { 
starttime = system.currenttimemillis(); 
} else { 
/** 
* we do do all calculations in long to reduce software float 
* calculations. we use 1000 as it gives us good accuracy and 
* small rounding errors 
*/ 
long normalizedtime = (1000 * (system.currenttimemillis() - starttime)) 
/ animation_duration_ms; 
normalizedtime = math.max(math.min(normalizedtime, 1000), 0); 
final int deltay = math 
.round((scrollfromy - scrolltoy) 
* interpolator 
.getinterpolation(normalizedtime / 1000f)); 
this.currenty = scrollfromy - deltay; 
setheaderscroll(currenty); 
} 
// if we're not at the target y, keep going... 
if (continuerunning && scrolltoy != currenty) { 
handler.postdelayed(this, animation_fps); 
} 
} 
public void stop() { 
this.continuerunning = false; 
this.handler.removecallbacks(this); 
} 
}; 
// =========================================================== 
// constants 
// =========================================================== 
static final float friction = 2.0f; 
static final int pull_to_refresh = 0x0; 
static final int release_to_refresh = 0x1; 
static final int refreshing = 0x2; 
static final int manual_refreshing = 0x3; 
public static final int mode_pull_down_to_refresh = 0x1; 
public static final int mode_pull_up_to_refresh = 0x2; 
public static final int mode_both = 0x3; 
// =========================================================== 
// fields 
// =========================================================== 
private int touchslop; 
private float initialmotiony; 
private float lastmotionx; 
private float lastmotiony; 
private boolean isbeingdragged = false; 
private int state = pull_to_refresh; 
private int mode = mode_pull_up_to_refresh; 
private int currentmode; 
private boolean disablescrollingwhilerefreshing = true; 
t refreshableview; 
private boolean ispulltorefreshenabled = true; 
private loadinglayout headerlayout; 
private loadinglayout footerlayout; 
private int headerheight; 
private final handler handler = new handler(); 
private onrefreshlistener onrefreshlistener; 
private smoothscrollrunnable currentsmoothscrollrunnable; 
// =========================================================== 
// constructors 
// =========================================================== 
public pulltorefreshbase(context context) { 
super(context); 
init(context, null); 
} 
public pulltorefreshbase(context context, int mode) { 
super(context); 
this.mode = mode; 
init(context, null); 
} 
public pulltorefreshbase(context context, attributeset attrs) { 
super(context, attrs); 
init(context, attrs); 
} 
// =========================================================== 
// getter & setter 
// =========================================================== 
/** 
* deprecated. use {@link #getrefreshableview()} from now on. 
* 
* @deprecated 
* @return the refreshable view which is currently wrapped 
*/ 
public final t getadapterview() { 
return refreshableview; 
} 
/** 
* get the wrapped refreshable view. anything returned here has already been 
* added to the content view. 
* 
* @return the view which is currently wrapped 
*/ 
public final t getrefreshableview() { 
return refreshableview; 
} 
/** 
* whether pull-to-refresh is enabled 
* 
* @return enabled 
*/ 
public final boolean ispulltorefreshenabled() { 
return ispulltorefreshenabled; 
} 
/** 
* returns whether the widget has disabled scrolling on the refreshable view 
* while refreshing. 
* 
* @return true if the widget has disabled scrolling while refreshing 
*/ 
public final boolean isdisablescrollingwhilerefreshing() { 
return disablescrollingwhilerefreshing; 
} 
/** 
* returns whether the widget is currently in the refreshing state 
* 
* @return true if the widget is currently refreshing 
*/ 
public final boolean isrefreshing() { 
return state == refreshing || state == manual_refreshing; 
} 
/** 
* by default the widget disabled scrolling on the refreshable view while 
* refreshing. this method can change this behaviour. 
* 
* @param disablescrollingwhilerefreshing 
* - true if you want to disable scrolling while refreshing 
*/ 
public final void setdisablescrollingwhilerefreshing( 
boolean disablescrollingwhilerefreshing) { 
this.disablescrollingwhilerefreshing = disablescrollingwhilerefreshing; 
} 
/** 
* mark the current refresh as complete. will reset the ui and hide the 
* refreshing view 
*/ 
public final void onrefreshcomplete() { 
if (state != pull_to_refresh) { 
resetheader(); 
if (onshowlayoutlistener != null) { 
onshowlayoutlistener.ondismiss(); 
} 
} 
} 
/** 
* set onrefreshlistener for the widget 
* 
* @param listener 
* - listener to be used when the widget is set to refresh 
*/ 
public final void setonrefreshlistener(onrefreshlistener listener) { 
onrefreshlistener = listener; 
} 
/** 
* auto load headerlayout to refresh 
* 
* @param listener 
*/ 
public final void setfirstautopulluptorefresh(onrefreshlistener listener) { 
setrefreshinginternal(true, mode_pull_down_to_refresh); 
listener.onrefresh(mode_pull_down_to_refresh); 
} 
/** 
* set refreshlable , default use null 
* 
* @param pulllabel 
* @param releaselabel 
* @param refreshinglabel 
*/ 
public void setrefreshlabel(string pulllabel, string releaselabel, 
string refreshinglabel) { 
if (pulllabel != null) { 
setpulllabel(pulllabel); 
} 
if (releaselabel != null) { 
setreleaselabel(releaselabel); 
} 
if (refreshinglabel != null) { 
setrefreshinglabel(refreshinglabel); 
} 
} 
/** 
* a mutator to enable/disable pull-to-refresh for the current view 
* 
* @param enable 
* whether pull-to-refresh should be used 
*/ 
public final void setpulltorefreshenabled(boolean enable) { 
this.ispulltorefreshenabled = enable; 
} 
/** 
* set text to show when the widget is being pulled, and will refresh when 
* released 
* 
* @param releaselabel 
* - string to display 
*/ 
private void setreleaselabel(string releaselabel) { 
if (null != headerlayout) { 
headerlayout.setreleaselabel(releaselabel); 
} 
if (null != footerlayout) { 
footerlayout.setreleaselabel(releaselabel); 
} 
} 
/** 
* set text to show when the widget is being pulled 
* 
* @param pulllabel 
* - string to display 
*/ 
private void setpulllabel(string pulllabel) { 
if (null != headerlayout) { 
headerlayout.setpulllabel(pulllabel); 
} 
if (null != footerlayout) { 
footerlayout.setpulllabel(pulllabel); 
} 
} 
/** 
* set text to show when the widget is refreshing 
* 
* @param refreshinglabel 
* - string to display 
*/ 
private void setrefreshinglabel(string refreshinglabel) { 
if (null != headerlayout) { 
headerlayout.setrefreshinglabel(refreshinglabel); 
} 
if (null != footerlayout) { 
footerlayout.setrefreshinglabel(refreshinglabel); 
} 
} 
public final void setrefreshing() { 
this.setrefreshing(true); 
} 
/** 
* sets the widget to be in the refresh state. the ui will be updated to 
* show the 'refreshing' view. 
* 
* @param doscroll 
* - true if you want to force a scroll to the refreshing view. 
*/ 
public final void setrefreshing(boolean doscroll) { 
if (!isrefreshing()) { 
setrefreshinginternal(doscroll); 
state = manual_refreshing; 
} 
} 
public final boolean haspullfromtop() { 
return currentmode != mode_pull_up_to_refresh; 
} 
// =========================================================== 
// methods for/from superclass/interfaces 
// =========================================================== 
@override 
public final boolean ontouchevent(motionevent event) { 
if (!ispulltorefreshenabled) { 
return false; 
} 
if (isrefreshing() && disablescrollingwhilerefreshing) { 
return true; 
} 
if (event.getaction() == motionevent.action_down 
&& event.getedgeflags() != 0) { 
return false; 
} 
switch (event.getaction()) { 
case motionevent.action_move: { 
if (isbeingdragged) { 
if (math.abs(event.gety() - downlocation) > 5 
&& onshowlayoutlistener != null) { 
onshowlayoutlistener.onshow(); 
} 
lastmotiony = event.gety(); 
this.pullevent(); 
return true; 
} 
break; 
} 
case motionevent.action_down: { 
if (isreadyforpull()) { 
downlocation = event.gety(); 
lastmotiony = initialmotiony = event.gety(); 
return true; 
} 
break; 
} 
case motionevent.action_cancel: 
case motionevent.action_up: { 
if (isbeingdragged) { 
isbeingdragged = false; 
if (state == release_to_refresh && null != onrefreshlistener) { 
setrefreshinginternal(true); 
onrefreshlistener.onrefresh(currentmode); 
} else { 
smoothscrollto(0); 
if (onshowlayoutlistener != null) { 
onshowlayoutlistener.ondismiss(); 
} 
} 
return true; 
} 
break; 
} 
} 
return false; 
} 
// remeber to down location 
private float downlocation = 0; 
@override 
public final boolean onintercepttouchevent(motionevent event) { 
if (!ispulltorefreshenabled) { 
return false; 
} 
if (isrefreshing() && disablescrollingwhilerefreshing) { 
return true; 
} 
final int action = event.getaction(); 
if (action == motionevent.action_cancel 
|| action == motionevent.action_up) { 
isbeingdragged = false; 
return false; 
} 
if (action != motionevent.action_down && isbeingdragged) { 
return true; 
} 
switch (action) { 
case motionevent.action_move: { 
if (isreadyforpull()) { 
final float y = event.gety(); 
final float dy = y - lastmotiony; 
final float ydiff = math.abs(dy); 
final float xdiff = math.abs(event.getx() - lastmotionx); 
if (ydiff > touchslop && ydiff > xdiff) { 
if ((mode == mode_pull_down_to_refresh || mode == mode_both) 
&& dy >= 0.0001f && isreadyforpulldown()) { 
lastmotiony = y; 
isbeingdragged = true; 
if (mode == mode_both) { 
currentmode = mode_pull_down_to_refresh; 
} 
} else if ((mode == mode_pull_up_to_refresh || mode == mode_both) 
&& dy <= 0.0001f && isreadyforpullup()) { 
lastmotiony = y; 
isbeingdragged = true; 
if (mode == mode_both) { 
currentmode = mode_pull_up_to_refresh; 
} 
} 
} 
} 
break; 
} 
case motionevent.action_down: { 
if (isreadyforpull()) { 
lastmotiony = initialmotiony = event.gety(); 
lastmotionx = event.getx(); 
isbeingdragged = false; 
} 
break; 
} 
case motionevent.action_up: 
break; 
} 
setrefreshlabel(currentmode); 
return isbeingdragged; 
} 
protected void addrefreshableview(context context, t refreshableview) { 
addview(refreshableview, new linearlayout.layoutparams( 
layoutparams.fill_parent, 0, 1.0f)); 
} 
/** 
* this is implemented by derived classes to return the created view. if you 
* need to use a custom view (such as a custom listview), override this 
* method and return an instance of your custom class. 
* 
* be sure to set the id of the view in this method, especially if you're 
* using a listactivity or listfragment. 
* 
* @param context 
* @param attrs 
* attributeset from wrapped class. means that anything you 
* include in the xml layout declaration will be routed to the 
* created view 
* @return new instance of the refreshable view 
*/ 
protected abstract t createrefreshableview(context context, 
attributeset attrs); 
public final int getcurrentmode() { 
return currentmode; 
} 
protected final loadinglayout getfooterlayout() { 
return footerlayout; 
} 
protected final loadinglayout getheaderlayout() { 
return headerlayout; 
} 
protected final int getheaderheight() { 
return headerheight; 
} 
protected final int getmode() { 
return mode; 
} 
/** 
* implemented by derived class to return whether the view is in a state 
* where the user can pull to refresh by scrolling down. 
* 
* @return true if the view is currently the correct state (for example, top 
* of a listview) 
*/ 
protected abstract boolean isreadyforpulldown(); 
/** 
* implemented by derived class to return whether the view is in a state 
* where the user can pull to refresh by scrolling up. 
* 
* @return true if the view is currently in the correct state (for example, 
* bottom of a listview) 
*/ 
protected abstract boolean isreadyforpullup(); 
// =========================================================== 
// methods 
// =========================================================== 
protected void resetheader() { 
state = pull_to_refresh; 
isbeingdragged = false; 
if (null != headerlayout) { 
headerlayout.reset(); 
} 
if (null != footerlayout) { 
footerlayout.reset(); 
} 
smoothscrollto(0); 
} 
/** 
* unless special requirements to call the method ,default call the method 
* {@link #setrefreshinginternal(boolean doscroll)} 
* 
* @param doscroll 
* @param mode 
*/ 
protected void setrefreshinginternal(boolean doscroll, int mode) { 
state = refreshing; 
setrefreshlabel(mode); 
if (null != headerlayout) { 
headerlayout.refreshing(); 
} 
if (doscroll) { 
smoothscrollto(mode == mode_pull_down_to_refresh ? -headerheight 
: headerheight); 
} 
} 
/** 
* set last refresh time 
* 
* @param time 
*/ 
public void setrefreshtime(string time) { 
textview mheadertimeview = (textview) headerlayout 
.findviewbyid(r.id.xlistview_header_time); 
mheadertimeview.settext(time); 
} 
public void setrefreshtime(long time){ 
textview mheadertimeview = (textview) headerlayout 
.findviewbyid(r.id.xlistview_header_time); 
mheadertimeview.settext(timeutil.getchattime(time)); 
} 
protected void setrefreshinginternal(boolean doscroll) { 
state = refreshing; 
setrefreshlabel(currentmode); 
if (null != footerlayout) { 
footerlayout.refreshing(); 
} 
if (null != headerlayout) { 
headerlayout.refreshing(); 
} 
if (doscroll) { 
smoothscrollto(currentmode == mode_pull_down_to_refresh ? -headerheight 
: headerheight); 
} 
} 
private void setrefreshlabel(int mode) { 
if (mode == mode_pull_down_to_refresh) { 
setrefreshlabel("涓嬫媺鍒锋柊", "閲婃斁绔嬪嵆鍒锋柊", "姝e湪鍒锋柊"); 
} 
if (mode == mode_pull_up_to_refresh) { 
setrefreshlabel("涓婃媺鑾峰彇鏇村", "鏉惧紑鏄剧ず鏇村", "姝e湪鍔犺浇"); 
} 
} 
protected final void setheaderscroll(int y) { 
scrollto(0, y); 
} 
protected final void smoothscrollto(int y) { 
if (null != currentsmoothscrollrunnable) { 
currentsmoothscrollrunnable.stop(); 
} 
if (this.getscrolly() != y) { 
this.currentsmoothscrollrunnable = new smoothscrollrunnable( 
handler, getscrolly(), y); 
handler.post(currentsmoothscrollrunnable); 
} 
} 
public void init(int mode) { 
// loading view strings 
string pulllabel = context 
.getstring(r.string.pull_to_refresh_pull_label); 
string refreshinglabel = context 
.getstring(r.string.pull_to_refresh_refreshing_label); 
string releaselabel = context 
.getstring(r.string.pull_to_refresh_release_label); 
// add loading views 
if (mode == mode_pull_down_to_refresh || mode == mode_both) { 
headerlayout = new loadinglayout(context,mode_pull_down_to_refresh, releaselabel, pulllabel,refreshinglabel); 
addview(headerlayout, 0, new linearlayout.layoutparams(viewgroup.layoutparams.fill_parent,viewgroup.layoutparams.wrap_content)); 
measureview(headerlayout); 
headerheight = headerlayout.getmeasuredheight(); 
} 
if (mode == mode_pull_up_to_refresh || mode == mode_both) { 
footerlayout = new loadinglayout(context, mode_pull_up_to_refresh,releaselabel, pulllabel, refreshinglabel); 
addview(footerlayout, new linearlayout.layoutparams( 
viewgroup.layoutparams.fill_parent, 
viewgroup.layoutparams.wrap_content)); 
measureview(footerlayout); 
headerheight = footerlayout.getmeasuredheight(); 
} 
// styleables from xml 
if (null != headerlayout) { 
// headerlayout.settextcolor(color.black); 
} 
if (null != footerlayout) { 
// footerlayout.settextcolor(color.black); 
} 
// hide loading views 
switch (mode) { 
case mode_both: 
setpadding(0, -headerheight, 0, -headerheight); 
break; 
case mode_pull_up_to_refresh: 
setpadding(0, 0, 0, -headerheight); 
break; 
case mode_pull_down_to_refresh: 
default: 
setpadding(0, -headerheight, 0, 0); 
break; 
} 
// if we're not using mode_both, then just set currentmode to current 
// mode 
if (mode != mode_both) { 
currentmode = mode; 
} 
this.mode = mode; 
} 
private void init(context context, attributeset attrs) { 
this.context = context; 
setorientation(linearlayout.vertical); 
touchslop = viewconfiguration.gettouchslop(); 
// refreshable view 
// by passing the attrs, we can add listview/gridview params via xml 
refreshableview = this.createrefreshableview(context, attrs); 
this.addrefreshableview(context, refreshableview); 
} 
private context context; 
private void measureview(view child) { 
viewgroup.layoutparams p = child.getlayoutparams(); 
if (p == null) { 
p = new viewgroup.layoutparams(viewgroup.layoutparams.fill_parent, 
viewgroup.layoutparams.wrap_content); 
} 
int childwidthspec = viewgroup.getchildmeasurespec(0, 0 + 0, p.width); 
int lpheight = p.height; 
int childheightspec; 
if (lpheight > 0) { 
childheightspec = measurespec.makemeasurespec(lpheight, 
measurespec.exactly); 
} else { 
childheightspec = measurespec.makemeasurespec(0, 
measurespec.unspecified); 
} 
child.measure(childwidthspec, childheightspec); 
} 
/** 
* actions a pull event 
* 
* @return true if the event has been handled, false if there has been no 
* change 
*/ 
private boolean pullevent() { 
final int newheight; 
final int oldheight = this.getscrolly(); 
switch (currentmode) { 
case mode_pull_up_to_refresh: 
newheight = math.round(math.max(initialmotiony - lastmotiony, 0) 
/ friction); 
// newheight = math.round((initialmotiony - lastmotiony) / 
// friction); 
break; 
case mode_pull_down_to_refresh: 
default: 
newheight = math.round(math.min(initialmotiony - lastmotiony, 0) 
/ friction); 
// newheight = math.round((initialmotiony - lastmotiony) / 
// friction); 
break; 
} 
setheaderscroll(newheight); 
if (newheight != 0) { 
if (state == pull_to_refresh && headerheight < math.abs(newheight)) { 
state = release_to_refresh; 
switch (currentmode) { 
case mode_pull_up_to_refresh: 
footerlayout.releasetorefresh(); 
break; 
case mode_pull_down_to_refresh: 
headerlayout.releasetorefresh(); 
break; 
} 
return true; 
} else if (state == release_to_refresh 
&& headerheight >= math.abs(newheight)) { 
state = pull_to_refresh; 
switch (currentmode) { 
case mode_pull_up_to_refresh: 
footerlayout.pulltorefresh(); 
break; 
case mode_pull_down_to_refresh: 
headerlayout.pulltorefresh(); 
break; 
} 
return true; 
} 
} 
return oldheight != newheight; 
} 
private boolean isreadyforpull() { 
switch (mode) { 
case mode_pull_down_to_refresh: 
return isreadyforpulldown(); 
case mode_pull_up_to_refresh: 
return isreadyforpullup(); 
case mode_both: 
return isreadyforpullup() || isreadyforpulldown(); 
} 
return false; 
} 
// =========================================================== 
// inner and anonymous classes 
// =========================================================== 
public static interface onrefreshlistener { 
public void onrefresh(int mode); 
} 
private onshowlayoutlistener onshowlayoutlistener; 
public void setonshowlayoutlistener(onshowlayoutlistener listener) { 
this.onshowlayoutlistener = listener; 
} 
public static interface onshowlayoutlistener { 
/** 
* 鏄惁姝e湪鏄剧ず搴曢儴甯冨眬 
*/ 
public void onshow(); 
/** 
* 鏄惁娑堝け 
*/ 
public void ondismiss(); 
} 
public static interface onlastitemvisiblelistener { 
public void onlastitemvisible(); 
} 
@override 
public void setlongclickable(boolean longclickable) { 
getrefreshableview().setlongclickable(longclickable); 
} 
}

主要代码都在上面贴出来了,当然还是一定要有demo

demo源码下载

这个源码里面 我把 pulltorefreshexpandablelistview 和 pulltorefreshlistview 也都放进来了,一样的逻辑。希望对大家有用。如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!