Pulltorefresh This library is very at most, GitHub today mainly analyze the implementation of the source code.
We analyze it through the dropdown refresh of the ListView, other similar.
The entire dropdown refresh parent view is LinearLayout, adding header view, Footer view, and ListView in LinearLayout
Pulltorefreshbase is the parent class that extends the linearlayout horizontal layout if we use the ListView need to watch subclass Pulltorefreshadapterviewbase-Pulltorefreshlistv Iew
Initialization code in the Pulltorefreshbase init method
Key code:
Refreshable view//by passing the attrs, we can add listview/gridview params via Xmlmrefreshableview = Createrefreshabl Eview (context, attrs);//Addrefreshableview (context, Mrefreshableview) via sub-class View,listview or scrollview;// Add view to Layout//We need to create now layouts now creates header and footer view, default is invisible, to add to parent window Mheaderlayout = Createloadinglayout (context, Mode.pull_from_start, a); mfooterlayout = createloadinglayout (Context, mode.pull_from_ END, a); Handlestyledattributes (a);//Add Loadingview effect, here is to add the view to the ListView Headerview inside to Updateuiformode (); Add a layout to the parent view
protected void Updateuiformode () {final Linearlayout.layoutparams LP = Getloadinglayoutlayoutparams ();//Remove Header, And then the add Header Loading View again if neededif (this = = Mheaderlayout.getparent ()) {Removeview (mheaderlayout);} if (Mmode.showheaderloadinglayout ()) {addviewinternal (mheaderlayout, 0, LP);//Add view to linearlayout}//Remove Footer, And then add Footer Loading View again if neededif (this = = Mfooterlayout.getparent ()) {Removeview (mfooterlayout);} if (Mmode.showfooterloadinglayout ()) {addviewinternal (mfooterlayout, LP);//Add view to linearlayout}//Hide Loading Viewsrefreshloadingviewssize ();//Hide Headerview, its practical is padding the way to set negative to the top of the screen//If we ' re not using Mode.both, set Mcurrentmode to Mmode, otherwise//set it to pull Downmcurrentmode = (Mmode! = Mode.both)? MMode:Mode.PULL_FROM_START;}
There are 2 Loadingview, one is added to the LinearLayout, and the other is added to the header of the ListView itself.
See where the Handlestyledattributes method is positioned to sub-category replication
Framelayout frame = new Framelayout (GetContext ());
Mheaderloadingview = Createloadinglayout (GetContext (), Mode.pull_from_start, a);
Mheaderloadingview.setvisibility (View.gone);
Frame.addview (Mheaderloadingview, LP);
Mrefreshableview.addheaderview (frame, null, FALSE);//Add Loadingview to the ListView header
Headerview altogether has 2 loadingview, one is added to LinearLayout one is added to the ListView Headerview
The Addviewinternal method is to join the LinearLayout parent class
See loadinglayout There are 2 kinds of fliploadinglayout and rotateloadinglayout we use to rotate the loading animation
A rotated picture on the left and a text and time hint on the right
The first loadinglayout main display: drop-down refresh, release to refresh
The second loadinglayout shows the text after letting go: loading ...
Structure is like this
When the UI is initialized well, take a look at the Ontouch drop-down capture event
Public Final Boolean ontouchevent (Motionevent event) {if (!ispulltorefreshenabled ()) {return false;} If we ' re refreshing, and the flag is set. Eat the Eventif (!mscrollingwhilerefreshingenabled && isrefreshing ()) {return true;} if (event.getaction () = = Motionevent.action_down && event.getedgeflags ()! = 0) {return false;} Switch (event.getaction ()) {case Motionevent.action_move: {if (misbeingdragged) {mlastmotiony = Event.gety (); Mlastmotionx = Event.getx ();p ullevent ();//start pull down, move return true;} break;} Case Motionevent.action_down: {if (Isreadyforpull ()) {//press Start dropdown mlastmotiony = Minitialmotiony = Event.gety (); Mlastmotionx = Minitialmotionx = Event.getx (); return true;} break;} Case MotionEvent.ACTION_CANCEL:case motionevent.action_up: {//stop pull down when if (misbeingdragged) {misbeingdragged = False;if (Mstate = = state.release_to_refresh&& (null! = Monrefreshlistener | | null! = MONREFRESHLISTENER2)) {SetState (state.refreshing, true);//Drop the finger to start the callback, execute our callback task return true;} If we ' re alReady refreshing, just scroll back to the TOPIF (Isrefreshing ()) {Smoothscrollto (0); return true;} If We haven ' t returned by here and then we ' re not in a state//to pulled, so just resetsetstate (State.reset); Revert to the original UI state return true;} Break;}} return false;}
Look at the Pullevent method private void Pullevent () {final int newscrollvalue;final int itemdimension;final float initialmotionvalue, Lastmotionvalue;switch (Getpulltorefreshscrolldirection ()) {case horizontal:initialmotionvalue = MInitialMotionX; Lastmotionvalue = Mlastmotionx;break;case VERTICAL:default:initialMotionValue = Minitialmotiony;lastmotionvalue = Mlastmotiony;break;} Calculate how many switch moves the dropdown (mcurrentmode) {case pull_from_end://pull-up NewScrollValue = Math.Round (Math.max (Initialmotionvalue- Lastmotionvalue, 0)/friction); itemdimension = getFooterSize (); Break;case pull_from_start://drop-down default: NewScrollValue = Math.Round (math.min (initialmotionvalue-lastmotionvalue, 0)/friction); itemdimension = GetHeaderSize (); break;} Show Headerview get moved value, can let Loadingview show Setheaderscroll (NewScrollValue); if (NewScrollValue! = 0 &&! Isrefreshing ()) {Float scale = Math.Abs (newscrollvalue)/(float) itemdimension;switch (mcurrentmode) {case Pull_from_ END:mFooterLayout.onPull (scale); Break;case pull_from_start:dEfault:mHeaderLayout.onPull (scale);//rotate the loading image on the left, display text and pictures This place will eventually execute the Onpullimpl method break in Loadinglayout;} The update status includes 2 in the release press Touch, and also the touch if the hands are not released if (mstate! = State.pull_to_refresh && itemdimension >= math.abs ( NewScrollValue)) {setState (State.pull_to_refresh);} else if (mstate = = State.pull_to_refresh && itemdimension & Lt Math.Abs (NewScrollValue)) {setState (State.release_to_refresh);//pull down and let go.}}}
And look at the Setheaderscroll method code protected final void Setheaderscroll (int value) {if (DEBUG) {log.d (Log_tag, "setheaderscroll:" + V Alue);} if (DEBUG) {log.d (Log_tag, "Setheaderscroll:" + value);} Clamp value to with pull scroll rangefinal int maximumpullscroll = Getmaximumpullscroll (); value = Math.min (maximumpulls Croll, Math.max (-maximumpullscroll, value)), if (mlayoutvisibilitychangesenabled) {if (value < 0) {// There is a displacement to show mheaderlayout.setvisibility (view.visible);} else if (value > 0) {<span style= "font-family:arial, Helvetica, Sans-serif;" >//has a displacement to show </span>mfooterlayout.setvisibility (view.visible);} else {mheaderlayout.setvisibility (view.invisible); mfooterlayout.setvisibility (view.invisible);}} if (use_hw_layers) {/** * use a Hardware Layer on the refreshable View if we've scrolled at * all. We don ' t use them on the Header/footer views as they change * often, which would negate any HW layer performance boost. */viewcompat.setlayertype (mrefreshableviewwrapper, Value! = 0?) View.LAYER_TYPE_HARDWARE:View.LAYER_TYPE_NONE);} Back to the most primitive scrollTo the most commonly used mobile layout switch (getpulltorefreshscrolldirection ()) {case Vertical:scrollto (0, value); break;case Horizontal:scrollto (value, 0); break;}}
SetState (state.refreshing, true);//Pull the top down, execute the Onrefreshing method, and call back the task interface we implemented, which is Onrefreshlistener
protected void Onrefreshing (final Boolean doscroll) {if (Mmode.showheaderloadinglayout ()) {mheaderlayout.refreshing () ;} if (Mmode.showfooterloadinglayout ()) {mfooterlayout.refreshing ();} if (doscroll) {if (mshowviewwhilerefreshing) {//Call Refresh Listener when the Scroll have Finishedonsmoothscrollfinishedl Istener listener = new Onsmoothscrollfinishedlistener () {@Overridepublic void onsmoothscrollfinished () { Callrefreshlistener ();//callback Interface Execution}};switch (mcurrentmode) {case Manual_refresh_only:case Pull_from_end:smoothscrollto (getFooterSize (), listener); Break;default:case Pull_from_start:smoothscrollto (-getheadersize (), listener); break;}} else {smoothscrollto (0);//Return to original position}} else {//We ' re not scrolling, so just call Refresh Listener Nowcallrefreshlistener (); /callback Interface Execution}}
private void Callrefreshlistener () {if (null! = Monrefreshlistener) {Monrefreshlistener.onrefresh (this);//callback} else if ( Null! = MOnRefreshListener2) {//This is the case of pull-up, drop-down all, use onrefreshlistener2if (Mcurrentmode = = Mode.pull_from_start) { Monrefreshlistener2.onpulldowntorefresh (this);} else if (Mcurrentmode = = mode.pull_from_end) {Monrefreshlistener2.onpulluptorefresh (this);}}}
Summary: The status includes the drop-down refresh, let go refresh, is refreshing, loading hidden. Moving the UI is also a scrollto of the most basic code. Animation section can see the loadinglayout of the 2 sub-classes
The main thing is that there are many details that are not analyzed. Please say thank you if you have any questions.
Open source Android-pulltorefresh drop-down refresh source analysis