public class Pulltoloadlistview extends ListView implements Onscrolllistener {
private static final String TAG = PullToLoadListView.class.getSimpleName ();
private static final int state_non = 0;
private static final int state_pull_to_refresh = 1;
private static final int state_release_to_refresh = 2;
private static final int state_refreshing = 3;
private int state;
private int firstvisibleitem;
private int lastvisisibleitem;
private float Prevy = 0;
Private View Headerview;
Private View Footerview;
Header Widgets
Private ProgressBar Headerprogressbar;
Private ImageView Headerimagearrow;
Private TextView HeaderText;
Private Rotateanimation Headerarrowanim;
Private Rotateanimation Headerarrowreverseanim;
Footer Widgets
Private ProgressBar Footerprogressbar;
Private TextView Footertext;
Private Boolean headerishanding = false;
Private Boolean footerishanding = false;
private int headerheight;
private int footerheight;
Private Resetanimation Resetanim;
Private Onloadinglistener Onloadinglistener;
Private Onscrolllistener Onscrolllistener;
Public Pulltoloadlistview {
Super (context);
Init (context);
}
Public Pulltoloadlistview (context context, AttributeSet Attrs) {
Super (context, attrs);
Init (context);
}
private void init (context context) {
state = State_non;
Firstvisibleitem = 0;
Lastvisisibleitem = 0;
Layoutinflater Inflater = layoutinflater.from (context);
Headerview = inflater.inflate (R.layout.view_pull_header, NULL);
Footerview = inflater.inflate (r.layout.view_pull_footer, NULL);
Headerprogressbar = (ProgressBar) Headerview.findviewbyid (R.id.progressbar);
Headerimagearrow = (ImageView) Headerview.findviewbyid (R.id.arrow);
HeaderText = (TextView) Headerview.findviewbyid (R.id.text);
Headerarrowanim = new Rotateanimation (0, -180, animation.relative_to_self, 0.5f, Animation.relative_to_self, 0.5f);
Headerarrowanim.setduration (300);
Headerarrowanim.setfillafter (TRUE);
Headerarrowreverseanim = new Rotateanimation ( -180, 0, Animation.relative_to_self, 0.5f, Animation.relative_to_self, 0.5f);
Headerarrowreverseanim.setduration (300);
Headerarrowreverseanim.setfillafter (TRUE);
Footerprogressbar = (ProgressBar) Footerview.findviewbyid (R.id.progressbar);
Footertext = (TextView) Footerview.findviewbyid (R.id.text);
Measureview (Headerview);
Measureview (Footerview);
Headerheight = Headerview.getmeasuredheight ();
Footerheight = Footerview.getmeasuredheight ();
Headerview.setpadding (0,-1 * headerview.getmeasuredheight (), 0, 0);
Footerview.setpadding (0,-1 * footerview.getmeasuredheight (), 0, 0);
Headerview.invalidate ();
Footerview.invalidate ();
Addheaderview (Headerview, NULL, FALSE);
Addfooterview (Footerview, NULL, FALSE);
Super.setonscrolllistener (this);
}
private void Measureview (view view) {
viewgroup.layoutparams LP = View.getlayoutparams ();
  IF (LP = = null) {
   LP = new Viewgroup.layoutparams (ViewGroup.LayoutParams.MATCH_ PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childwidthspec = viewgroup.getchildmeasurespec (0, 0, lp.width);
int Childheightspec;
if (Lp.height > 0) {
childheightspec = measurespec.makemeasurespec (0, measurespec.exactly);
} else {
childheightspec = measurespec.makemeasurespec (0, measurespec.unspecified);
}
view.measure (Childwidthspec, Childheightspec);
}
private void Resetheader () {
Headerview.setpadding (0,-1 * headerheight, 0, 0);
Resetanim = new Resetanimation (Headerview, Headerheight, Headerview.getpaddingtop ());
Resetanim.start ();
}
private void Resetfooter () {
Resetanim = new Resetanimation (Footerview, Footerheight, Footerview.getpaddingtop ());
Resetanim.start ();
}
private void Changeheaderviewbystate (int state) {
if (this.state = = state) {
return;
}
int prevstate = this.state;
This.state = State;
Switch (state) {
Case State_non:
Headerprogressbar.setvisibility (view.invisible);
Headerimagearrow.setvisibility (view.visible);
Headerimagearrow.clearanimation ();
Headertext.settext ("Pull down to Refresh");
Break
Case State_pull_to_refresh:
Headerprogressbar.setvisibility (view.invisible);
Headerimagearrow.setvisibility (view.visible);
Headertext.settext ("Pull down to Refresh");
if (prevstate = = State_release_to_refresh) {
Headerimagearrow.startanimation (Headerarrowreverseanim);
} else {
Headerimagearrow.clearanimation ();
}
Break
Case State_release_to_refresh:
Headerprogressbar.setvisibility (view.invisible);
Headerimagearrow.setvisibility (view.visible);
Headerimagearrow.startanimation (Headerarrowanim);
Headertext.settext ("Release to Refresh");
Break
Case state_refreshing:
Headerprogressbar.setvisibility (view.visible);
Headerimagearrow.setvisibility (view.invisible);
Headerimagearrow.clearanimation ();
Headertext.settext ("refreshing");
Break
Default
Break
}
}
private void Changefooterviewbystate (int state) {
if (this.state = = state) {
return;
}
This.state = State;
switch (state) {
case State_non:
Footerprogressbar.setvisibility (view.invisible);
footertext.settext ("Pull up to Refresh");
break;
case State_pull_to_refresh:
footerprogressbar.setvisibility (View.INVISIBLE );
footertext.settext ("Pull up to Refresh");
break;
case State_release_to_refresh:
footerprogressbar.setvisibility ( view.invisible);
footertext.settext ("Release to Refresh");
break;
case state_refreshing:
footerprogressbar.setvisibility (View.VISIBLE);
footertext.settext ("refreshing");
break;
default:
break;
 &NBSP}
}
@Override
public void Setonscrolllistener (Onscrolllistener l) {
This.onscrolllistener = l;
}
public void Setonloadinglistener (Onloadinglistener onloadinglistener) {
This.onloadinglistener = Onloadinglistener;
}
public void loadcompleted () {
if (headerishanding) {
Changeheaderviewbystate (State_non);
Resetheader ();
Headerishanding = false;
}
if (footerishanding) {
Changefooterviewbystate (State_non);
Resetfooter ();
Footerishanding = false;
}
}
private void Handlemoveheaderevent (Motionevent ev) {
Headerishanding = true;
float tempy = Ev.getrawy ();
float vector = Tempy-prevy;
Vector/= 2;
Prevy = Tempy;
if (Vector > 0) {
int newpadding = (int) (headerview.getpaddingtop () + vector);
newpadding = Math.min (newpadding, HEADERHEIGHT/2);
Headerview.setpadding (0, newpadding, 0, 0);
if (state!= state_refreshing) {
if (newpadding > 0) {
Changeheaderviewbystate (State_release_to_refresh);
} else {
Changeheaderviewbystate (State_pull_to_refresh);
}
}
} else {
if (state = = State_release_to_refresh | | state = = State_pull_to_refresh) {
int newpadding = (int) (headerview.getpaddingtop () + vector);
newpadding = Math.max (newpadding,-1 * headerheight);
Headerview.setpadding (0, newpadding, 0, 0);
if (newpadding <=-1 * headerheight) {
Changeheaderviewbystate (State_non);
Headerishanding = false;
else if (newpadding <= 0) {
Changeheaderviewbystate (State_pull_to_refresh);
} else {
}
}
}
}
private void Handlemovefooterevent (Motionevent ev) {
Footerishanding = true;
float tempy = Ev.getrawy ();
float vector = Tempy-prevy;
Vector/= 2;
Prevy = Tempy;
if (vector < 0) {
int newpadding = (int) (Footerview.getpaddingtop ()-vector);
if (newpadding > 0) {
newpadding = 0;
}
Footerview.setpadding (0, newpadding, 0, 0);
if (state!= state_refreshing) {
if (newpadding < 0) {
Changefooterviewbystate (State_pull_to_refresh);
} else {
Changefooterviewbystate (State_release_to_refresh);
}
}
} else {
int newpadding = (int) (Footerview.getpaddingtop ()-vector);
newpadding = Math.min (newpadding, footerheight);
Footerview.setpadding (0, newpadding, 0, 0);
if (newpadding <=-1 * footerheight) {
Changefooterviewbystate (State_non);
Footerishanding = false;
else if (newpadding < 0) {
Changefooterviewbystate (State_pull_to_refresh);
}
}
}
@Override
public boolean ontouchevent (Motionevent ev) {
Switch (ev.getaction ()) {
Case Motionevent.action_down:
Prevy = Ev.getrawy ();
Break
Case MOTIONEVENT.ACTION_UP:
if (state = = State_release_to_refresh) {
if (headerishanding) {
Changeheaderviewbystate (state_refreshing);
if (Onloadinglistener!= null) {
Onloadinglistener.onloadnew ();
}
}
if (footerishanding) {
Changefooterviewbystate (state_refreshing);
if (Onloadinglistener!= null) {
Onloadinglistener.onloadmore ();
}
}
else if (state = = State_pull_to_refresh) {
if (headerishanding) {
Changeheaderviewbystate (State_non);
Resetheader ();
Headerishanding = false;
}
if (footerishanding) {
Changefooterviewbystate (State_non);
Resetfooter ();
Footerishanding = false;
}
else if (state = = State_non) {
Headerishanding = false;
Footerishanding = false;
} else {
state = = State_refreshing
Ignore
}
Break
Case Motionevent.action_move:
if (Resetanim = null | |!resetanim.run) {
if (state!= state_refreshing) {
Adapter Adapter = Getadapter ();
if (adapter = = NULL) {
Handlemoveheaderevent (EV);
} else {
Final int count = Adapter.getcount ();
if (count <= 0) {
Handlemoveheaderevent (EV);
} else {
float tempy = Ev.getrawy ();
float vector = Tempy-prevy;
if (Firstvisibleitem = = 0 && Lastvisisibleitem = = count-1) {
if (headerishanding) {
Handlemoveheaderevent (EV);
else if (footerishanding) {
Handlemovefooterevent (EV);
} else {
if (Vector > 0) {
Handlemoveheaderevent (EV);
else if (vector < 0) {
Handlemovefooterevent (EV);
} else {
Ignore vector = = 0
}
}
else if (Firstvisibleitem = = 0 && vector > 0) {
Handlemoveheaderevent (EV);
else if (Lastvisisibleitem = count-1 && Vector < 0) {
Handlemovefooterevent (EV);
} else {
Ignore
}
}
}
}
}
Break
Default
Break
}
return super.ontouchevent (EV);
}
@Override
public void onscrollstatechanged (Abslistview view, int scrollstate) {
if (Onscrolllistener!= null) {
Onscrolllistener.onscrollstatechanged (view, scrollstate);
}
}
@Override
public void Onscroll (Abslistview view, int firstvisibleitem,
int visibleitemcount, int totalitemcount) {
This.firstvisibleitem = Firstvisibleitem;
This.lastvisisibleitem = Firstvisibleitem + visibleItemCount-1;
if (Onscrolllistener!= null) {
Onscrolllistener.onscroll (view, Firstvisibleitem, VisibleItemCount, Totalitemcount);
}
}
Static Class Resetanimation extends Thread {
static final int DURATION = 600;
static final int INTERVAL = 5;
View view;
int orignalheight;
int paddingtop;
Boolean run = false;
Resetanimation (view view, int orignalheight, int paddingtop) {
This.view = view;
This.orignalheight = Orignalheight;
This.paddingtop = paddingtop;
}
public void Run () {
Run = true;
int total = Orignalheight * 2 + paddingtop;
int timetotal = Duration/interval;
int piece = Total/timetotal;
int time = 0;
Final view view = This.view;
Final int paddingtop = This.paddingtop;
do {
Final int nextpaddingtop = Paddingtop-time * piece;
View.post (New Runnable () {
public void Run () {
View.setpadding (0, nextpaddingtop, 0, 0);
View.postinvalidate ();
}
});
try {
Sleep (INTERVAL);
catch (Interruptedexception e) {
E.printstacktrace ();
}
Time + +;
while (Time < timetotal);
Run = false;
}
}
Public interface Onloadinglistener {
public void onloadnew ();
public void Onloadmore ();
}
}