Android pull-down refresh and pull up to load more controls-supports listview, gridview, and scrollview

Source: Internet
Author: User

Milo, http://miloisbadboy.com/archives/55

Since this article is a little long, I will post some code here. For more information, see the original article.

 

 

 

Main source code

Package COM. miloisbadboy. view; import android. content. context; import android. util. attributeset; import android. util. displaymetrics; import android. util. log; import android. view. layoutinflater; import android. view. motionevent; import android. view. view; import android. view. viewgroup; import android. view. animation. linearinterpolator; import android. view. animation. rotateanimation; import android. widget. adaptervi EW; import android. widget. imageview; import android. widget. linearlayout; import android. widget. progressbar; import android. widget. scrollview; import android. widget. textview; import COM. miloisbadboy. r; public class pulltorefreshview extends linearlayout {Private Static final string tag = "pulltorefreshview"; // refresh statesprivate static final int pull_to_refresh = 2; Private Static final int release_to_r Efresh = 3; Private Static final int refreshing = 4; // pull stateprivate static final int pull_up_state = 0; Private Static final int pull_down_state = 1; /* ** last y */private int mlastmotiony;/* Lock */private Boolean mlock;/* Header view */private view mheaderview; /*** footer view */private view mfooterview;/*** list or grid */private adapterview <?> Madapterview;/***** scrollview */private scrollview mscrollview;/***** header view height */private int mheaderviewheight;/***** footer view height */private int mfooterviewheight; /*** header view image */private imageview mheaderimageview;/*** footer view image */private imageview mfooterimageview;/*** header tip text */private textview mheadertextview; /*** footer tip text */private textview MFO Otertextview;/*** header refresh time */private textview mheaderupdatetextview;/*** footer refresh time * // Private textview mfooterupdatetextview; /*** header progress bar */private progressbar mheaderprogressbar;/*** footer progress bar */private progressbar mfooterprogressbar;/*** layout Inflater */private layoutinflater minflater; /*** header view current state */private int mheaderstate; /*** Footer view current state */private int mfooterstate;/*** pull state, pull up or pull down; pull_up_state or pull_down_state */private int mpullstate; /*** changes to the downward arrow, and changes the arrow direction */private rotateanimation mflipanimation;/*** changes to the reverse arrow and rotates */private rotateanimation mreverseflipanimation; /*** footer refresh listener */private onfooterrefreshlistener monfooterrefreshlistener;/*** footer refresh listener */Private onheaderrefreshlistener monheaderrefreshlistener;/*** last update time */private string mlastupdatetime; Public pulltorefreshview (context, attributeset attrs) {super (context, attrs ); init ();} public pulltorefreshview (context) {super (context); Init ();} /*** init ** @ Description * @ Param context */private void Init () {// load all of the animations we need in code rather Through xmlmflipanimation = new rotateanimation (0,-180, rotateanimation. relative_to_self, 0.5f, rotateanimation. relative_to_self, 0.5f); mflipanimation. setinterpolator (New linearinterpolator (); mflipanimation. setduration (250); mflipanimation. setfillafter (true); mreverseflipanimation = new rotateanimation (-180, 0, rotateanimation. relative_to_self, 0.5f, rotateanimation. relative_to_self, 0.5f); mreverse Flipanimation. setinterpolator (New linearinterpolator (); mreverseflipanimation. setduration (250); mreverseflipanimation. setfillafter (true); minflater = layoutinflater. from (getcontext (); // header view is added here to ensure that it is the first addheaderview () added to the top of linearlayout;} private void addheaderview () {// header viewmheaderview = minflater. inflate (R. layout. refresh_header, this, false); mheaderimageview = (imageview) mheaderview. Findviewbyid (R. id. pull_to_refresh_image); mheadertextview = (textview) mheaderview. findviewbyid (R. id. pull_to_refresh_text); mheaderupdatetextview = (textview) mheaderview. findviewbyid (R. id. pull_to_refresh_updated_at); mheaderprogressbar = (progressbar) mheaderview. findviewbyid (R. id. pull_to_refresh_progress); // header layoutmeasureview (mheaderview); mheaderviewheight = mheaderview. getmeasuredheight (); Layoutparams Params = new layoutparams (layoutparams. match_parent, mheaderviewheight); // set the value of topmargin to the height of the negative header view, that is, hiding it in the top Params. topmargin =-(mheaderviewheight); // mheaderview. setlayoutparams (params1); addview (mheaderview, Params);} private void addfooterview () {// footer viewmfooterview = minflater. inflate (R. layout. refresh_footer, this, false); mfooterimageview = (imageview) mfooterview. findvi Ewbyid (R. id. pull_to_load_image); mfootertextview = (textview) mfooterview. findviewbyid (R. id. pull_to_load_text); mfooterprogressbar = (progressbar) mfooterview. findviewbyid (R. id. pull_to_load_progress); // footer layoutmeasureview (mfooterview); mfooterviewheight = mfooterview. getmeasuredheight (); layoutparams Params = new layoutparams (layoutparams. match_parent, mfooterviewheight); // int Top = getheight (); // Params. topmargin = getheight (); // here getheight () = 0, but getheight () has a value in the onintercepttouchevent () method and is no longer 0; // when will the getheight () value be assigned? Wait and try again. // because it is a linear layout, it can be directly added, as long as the height of adapterview is match_parent, then the footer view will be added to the end, and the addview (mfooterview, Params);} @ overrideprotected void onfinishinflate () {super. onfinishinflate (); // footer view add here to ensure that the last addfooterview (); initcontentadapterview ();}/*** init Adapter View like listview, gridview and so on; or init scrollview **/private void initcontentadapterview () {int COUNT = getchildcount (); If (count <3) {Throw new illegalargumentexception ("this layout must contain 3 child views, and adapterview or scrollview must in the second position! ");} View = NULL; For (INT I = 0; I <count-1; ++ I) {view = getchildat (I ); if (view instanceof adapterview <?>) {Madapterview = (adapterview <?>) View;} If (view instanceof scrollview) {// finish latermscrollview = (scrollview) view;} If (madapterview = NULL & mscrollview = NULL) {Throw new illegalargumentexception ("must contain a adapterview or scrollview in this layout! ") ;}} 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);} @ overridepublic Boolean onintercepttouchevent (motionevent e) {int y = (INT) E. getrawy (); Switch (E. getaction () {Case motionevent. action_down: // first intercept the down event and record the Y coordinate mlastmotiony = y; break; Case motionevent. action_move: // deltay> 0 indicates downward movement, and <0 indicates int de. Ltay = Y-mlastmotiony; If (isrefreshviewscroll (deltay) {return true;} break; Case motionevent. action_up: Case motionevent. action_cancel: break;} return false;}/** if the onintercepttouchevent () method does not intercept (that is, return * false in the onintercepttouchevent () method) it is processed by the sub-view of the pulltorefreshview; otherwise, it is processed by the following method (that is, it is handled by the pulltorefreshview itself) */@ overridepublic Boolean ontouchevent (motionevent event) {If (mlock) {return true;} int y = (I NT) event. getrawy (); Switch (event. getaction () {Case motionevent. action_down: // onintercepttouchevent has been recorded // mlastmotiony = y; break; Case motionevent. action_move: int deltay = Y-mlastmotiony; If (mpullstate = pull_down_state) {// pulltorefreshview execute the drop-down log. I (TAG, "Pull down! Parent view move! "); Headerpreparetorefresh (deltay); // setheaderpadding (-mheaderviewheight);} else if (mpullstate = pull_up_state) {// pulltorefreshview executes the pull log. I (TAG, "Pull up! Parent view move! "); Footerpreparetorefresh (deltay);} mlastmotiony = y; break; Case motionevent. action_up: Case motionevent. action_cancel: int topmargin = getheadertopmargin (); If (mpullstate = pull_down_state) {If (topmargin> = 0) {// start refreshing headerrefreshing ();} else {// No Refresh has been executed. Re-hide setheadertopmargin (-mheaderviewheight) ;}} else if (mpullstate = pull_up_state) {If (math. ABS (topmargin)> = mheaderviewheight + mfooterviewheight ){ // Start to execute footer refresh footerrefreshing ();} else {// refresh not executed yet, re-hide setheadertopmargin (-mheaderviewheight);} break;} return Super. ontouchevent (event);}/*** whether the parent view should be reached, that is, pulltorefreshview sliding ** @ Param deltay *, deltay> 0 is downward movement, <0 is the upward movement * @ return */private Boolean isrefreshviewscroll (INT deltay) {If (mheaderstate = refreshing | mfooterstate = refreshing) {return false ;} // For listview and gridviewif (madapter View! = NULL) {view child = madapterview. getchildat (0); If (child = NULL) {// if there is no data in madapterview, do not intercept // you can consider returning truereturn false ;} // The Sub-view (listview or gridview) slides to the top if (deltay> 0 & Child. gettop () = 0) {mpullstate = pull_down_state; return true;} else if (deltay <0) {view lastchild = madapterview. getchildat (madapterview. getchildcount ()-1); If (lastchild = NULL) {// If madapterview does not contain data, return false is not blocked;} // If the bottom of the last child view is smaller than the height of the parent view, the data of the madapterview is not filled with the parent view. // if the height is equal to that of the parent view, the madapterview has been moved to the end if (lastchild. getbottom () <= getheight () {mpullstate = pull_up_state; return true ;}}// for scrollviewif (mscrollview! = NULL) {// The Sub-scroll view slides to the top view child = mscrollview. getchildat (0); If (deltay> 0 & mscrollview. getscrolly () = 0) {mpullstate = pull_down_state; return true;} else if (deltay <0 & Child. getmeasuredheight () <= getheight () + mscrollview. getscrolly () {mpullstate = pull_up_state; return true;} return false;}/*** header preparation refresh, finger movement process, not released ** @ Param deltay *, finger sliding distance */private void headerpreparetorefresh (INT deltay) {int newtopmargin = changingheaderviewtopmargin (deltay); // when the header view topmargin> = 0, it indicates that it is completely displayed, modify the prompt status of the header view if (newtopmargin> = 0 & mheaderstate! = Release_to_refresh) {mheadertextview. settext (R. string. pull_to_refresh_release_label); mheaderupdatetextview. setvisibility (view. visible); mheaderimageview. clearanimation (); mheaderimageview. startanimation (mflipanimation); mheaderstate = release_to_refresh;}/*** footer is ready to refresh. The height of moving footer view is the same as that of moving header view, you can modify the topmargin value of the header view to ** @ Param deltay *. The distance between the fingers sliding */private voi. D footerpreparetorefresh (INT deltay) {int newtopmargin = changingheaderviewtopmargin (deltay ); // if the absolute value of the header view topmargin is greater than or equal to the height of the header + footer // The footer view is displayed completely, modify the prompt status of the footer view if (math. ABS (newtopmargin)> = (mheaderviewheight + mfooterviewheight) & mfooterstate! = Release_to_refresh) {mfootertextview. settext (R. string. pull_to_refresh_footer_release_label); mfooterimageview. clearanimation (); mfooterimageview. startanimation (mflipanimation); mfooterstate = release_to_refresh ;}} /*** modify the value of header view top margin * @ Description * @ Param deltay * @ return */private int changingheaderviewtopmargin (INT deltay) {layoutparams Params = (layoutparams) mheaderview. getlayoutpara MS (); float newtopmargin = Params. topmargin + deltay * 0.3f; Params. topmargin = (INT) newtopmargin; mheaderview. setlayoutparams (Params); invalidate (); Return Params. topmargin;}/*** header refreshing **/private void headerrefreshing () {mheaderstate = refreshing; setheadertopmargin (0); mheaderimageview. setvisibility (view. gone); mheaderimageview. clearanimation (); mheaderimageview. setimagedrawable (null); mhea Derprogressbar. setvisibility (view. Visible); mheadertextview. settext (R. String. pull_to_refresh_refreshing_label); If (monheaderrefreshlistener! = NULL) {monheaderrefreshlistener. trim (this) ;}/ *** footer refreshing **/private void footerrefreshing () {mfooterstate = refreshing; int Top = mheaderviewheight + mfooterviewheight; setheadertopmargin (-top ); mfooterimageview. setvisibility (view. gone); mfooterimageview. clearanimation (); mfooterimageview. setimagedrawable (null); mfooterprogressbar. setvisibility (view. visible); mfootertextview. sett EXT (R. String. pull_to_refresh_footer_refreshing_label); If (monfooterrefreshlistener! = NULL) {monfooterrefreshlistener. onfooterrefresh (this) ;}}/*** set the topmargin value of the header view ** @ Description * @ Param topmargin *. If the value is 0, the header view is displayed completely; -mheaderviewheight indicates that */private void setheadertopmargin (INT topmargin) {layoutparams Params = (layoutparams) mheaderview is completely hidden. getlayoutparams (); Params. topmargin = topmargin; mheaderview. setlayoutparams (Params); invalidate ();}/*** header View Restore the initial status after the update. **/Public void onheaderrefreshcomplete () {setheadertopmargin (-mheaderviewheight); mheaderimageview. setvisibility (view. visible); mheaderimageview. setimageresource (R. drawable. ic_pulltorefresh_arrow); mheadertextview. settext (R. string. pull_to_refresh_pull_label); mheaderprogressbar. setvisibility (view. gone); // mheaderupdatetextview. settext (""); mheaderstate = pull_to_refresh;}/*** resets the L Ist to a normal state after a refresh. * @ Param lastupdated last updated. */Public void initialize (charsequence lastupdated) {setlastupdated (lastupdated); onheaderrefreshcomplete ();}/*** restore the initial state after the footer view is updated */Public void onfooterrefreshcomplete () {setheadertopmargin (-mheaderviewheight); mfooterimageview. setvisibility (view. visible); mfooterimageview. setimageresource (R. drawable. Ic_pulltorefresh_arrow_up); mfootertextview. settext (R. string. pull_to_refresh_footer_pull_label); mfooterprogressbar. setvisibility (view. gone); // mheaderupdatetextview. settext (""); mfooterstate = pull_to_refresh;}/*** set a text to represent when the list was last updated. * @ Param lastupdated last updated. */Public void setlastupdated (charsequence lastupdated) {If (lastupdated! = NULL) {mheaderupdatetextview. setvisibility (view. visible); mheaderupdatetextview. settext (lastupdated);} else {mheaderupdatetextview. setvisibility (view. gone) ;}}/*** get the topmargin of the current header view ** @ Description */private int getheadertopmargin () {layoutparams Params = (layoutparams) mheaderview. getlayoutparams (); Return Params. topmargin;}/*** lock **/private void lock () {mlock = true;}/*** unlock **/private void unlock () {mlock = false;}/*** set headerrefreshlistener ** @ Description * @ Param headerrefreshlistener */Public void listener (expose headerrefreshlistener) {monheaderrefreshlistener = headerrefreshlistener ;} public void listener (inclufooterrefreshlistener) {monfooterrefreshlistener = footerrefreshlistener;}/*** interface definition for a callback to be invoked when list/GRID footer * view shold be refreshed. */public interface onfooterrefreshlistener {public void onfooterrefresh (pulltorefreshview view);}/*** interface definition for a callback to be invoked when list/GRID header * view shold be refreshed. */public interface onheaderrefreshlistener {public void onheaderrefresh (pulltorefreshview view );}}

  

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.