Build Android Magnum pull-up dropdown refresh frame--xrefreshview (ii)

Source: Internet
Author: User
Tags gety

First, preface

Since the last published build Android Magnum pull down refresh frame--xrefreshview (a), the period of the big half month has been very busy, but I do every night after work in the update and maintenance of Xrefreshview, but also according to some friends to solve some problems, This article was written because Xrefreshview has arrived at a phase of relatively reliable and stable functionality. Below I will introduce the latest features and usage of Xrefreshview, as well as the main ideas of implementation.

Second, update

2.1 To determine the change in the timing of pull-up pull-up

Before is through Refreshview.setrefreshviewtype (xrefreshviewtype.abslistview); this way to pre-set the type of view to select the corresponding judgment timing method, now no longer have to do so, changed to the following.

/** * @return Whether It is possible for the child view of this layout to * scroll up. Override this if the child view is a custom view. */public Boolean Canchildpulldown () {if (child instanceof Abslistview) {final Abslistview Abslistview = (abslistview) chil D;return canscrollvertically (Child,-1) | | Abslistview.getchildcount () > 0&& (abslistview.getfirstvisibleposition () > 0 | | abslistview.getchildat ( 0). GetTop () < Abslistview.getpaddingtop ());} else {return canscrollvertically (child,-1) | | child.getscrolly () > 0;}} public Boolean Canchildpullup () {if (child instanceof Abslistview) {Abslistview Abslistview = (abslistview) Child;return C Anscrollvertically (Child, 1) | | Abslistview.getlastvisibleposition ()! = mTotalItemCount-1;} else if (child instanceof WebView) {WebView WebView = (WebView) child;return canscrollvertically (Child, 1) | | webview.getco Ntentheight () * Webview.getscale ()! = Webview.getheight () + webview.getscrolly (); else if (child instanceof ScrolLView) {ScrollView ScrollView = (ScrollView) child; View Childview = scrollview.getchildat (0), if (childview! = null) {return canscrollvertically (Child, 1) | | Scrollview.getscrolly ()! = Childview.getheight ()-Scrollview.getheight ();}} Else{return canscrollvertically (Child, 1);} return true;} The/** * is used to determine if the view can be slid up or down in the vertical direction * @param View v * @param Direction direction negative number represents upward swipe, positive number is the inverse * @return */public boolean CANSCR Ollvertically (view view, int direction) {return viewcompat.canscrollvertically (view, direction);}
As you can see, viewcompat.canscrollvertically (view, direction) is a way to tell if a view can slide up or down, so you can tell if the view has reached the top or bottom, After 4.0 in a method is usually very useful, but 2.3.3 previously was not so, in order to be compatible with 2.3.3 I did some view type of judgment, through the type of view to provide special judgment to reach the top or bottom of the method. In general, the common view through the above methods can be accurately determine whether to reach the top or bottom, but if you want to refresh is a complex or custom view, can also be done in the following ways
Refreshview.setontoprefreshtime (New Ontoprefreshtime () {@Overridepublic Boolean istop () {return Stickylv.getfirstvisibleposition () = = 0;}}); Refreshview.setonbottomloadmoretime (New Onbottomloadmoretime () {@Overridepublic Boolean isbottom () {return Stickylv.getlastvisibleposition () = = MTotalItemCount-1;}});

Xrefreshview The judgment view to the top and bottom of the work to you to do, you just tell Xrefreshview when is the right time to refresh the time, and the last blog mentioned in the method is different,Xrefreshview this time provides two interfaces, the top and the bottom of the judgment time to separate, mainly considering the drop-down and pull-up loading sometimes not all needed.

Changes in the way the 2.2headview and Footview move up and down

At first, moving Headview and Footview I was moving through property animations

public static void Movechildandaddedview (View child, view Addview,float Childy, float addY, int during, Animatorlistener: . Listener) {//Property animation moves Objectanimator y = objectanimator.offloat (Child, "Y", child.gety (), childy); Objectanimator y2 = Objectanimator.offloat (AddView, "Y", addview.gety (), AddY); Animatorset animatorset = new Animatorset () animatorset.playtogether (y, y2); animatorset.setduration (during); if ( Listener.length > 0) animatorset.addlistener (listener[0]); Animatorset.start ();}
later, in order to be compatible with 2.3.3 I also downloaded a specialAnimated Open Source Library nineoldandroidsnineoldandroids,What the hell is this library for? In API3.0 (Honeycomb), the SDK has a new android.animation package, which is a class of animation-related classes, with the honeycomb API that enables very complex animation effects. But if developers want to use this set of APIs under 3.0, they need to use the open source framework nine old androids, which will determine its SDK version based on the machine we're running, and if it's API3.0 above, use the animated class from Android, or use nine Old Androids Library, this is a compatibility library. (Note: The red part of the word I was directly quoted Xiahanming Big God's blog original, has been watching his blog, so has been very impressed with him, his blog quality is very good. After the compatibility of the problem even handled, but later Xutils 4 group of Artillery told me, Xrefreshview in the drop when there will be jitter, I know this situation began to look for problems, and later found that because the property animation to move the header problem, Do not use the property animation is good, think carefully, the property animation is actually reflected to the property corresponding to the Get/set method to execute, after all, is reflected, and when the finger moves will trigger a lot of action_move, each action_move will do a reflection, Then there will be a lot of reflection work, a large number of intensive reflection will lead to a decrease in performance, so there is the situation of jitter. After giving up the reflection, I used the method of View.offsettopandbottom (DeltaY) to see the annotation of the method
/** * Offset This view's vertical location by the specified number of pixels. * * @param offset the number of pixels to offset the view by */
The translation is to move the view in pixels in a vertical direction. There's nothing to say, it's easy to use, you deserve it.

The 2.3demo has a flow-through layout

Very simple, interested to see


2.4 Click button to refresh and support rebound

Now there are support click button Refresh,

protected void Onresume () {super.onresume (); Xrefreshview.startrefresh ();}
There is also the ability to support setting whether pull-down refreshes and pull-up loads
Sets whether the drop-down refreshes refreshview.setpullrefreshenable (false);//sets whether the Refreshview.setpullloadenable (false) can be loaded on pull-up;
Cannon said that if you can not pull up and pull up and load the case can also have a rebound effect is good, so now the version is supported.

III. realization of relevant
3.1 Changes before and after

Before, I took Headview, refreshed Childview and Footview as three parts, and recorded the location of each view from the beginning.

/** * At the beginning of loading more, record the Y coordinate of Childview start */private float mchildy = -1;/** * At the beginning of loading more time, record the Footview start y coordinate */private flo at mfooty = -1;/** * When loading more at the beginning, record the Y coordinate of the Headview start */private float mheady =-1;
Then when the finger moves constantly update the current view of the y-coordinate, and finally to move the individual view, this inadvertently increased the workload and the complexity of the work, then I think of the three parts as a whole, so much simpler, it is no longer need so many variables.


3.2 Implementation Process

3.2.1 Measurement

/* * Measure the width and height of the view. Width is the width of the user set, height is header, content view, footer the height of the three child controls. *  * @see android.view.view#onmeasure (int, int) */@Overrideprotected void onmeasure (int widthmeasurespec, int Heightmeasurespec) {super.onmeasure (Widthmeasurespec, heightmeasurespec); int width = Measurespec.getsize (  WIDTHMEASURESPEC); int childCount = Getchildcount (); int finalheight = 0;for (int i = 0; i < ChildCount; i++) {View child = Getchildat (i); Measurechild (Child, Widthmeasurespec, Heightmeasurespec); Finalheight + = Child.getmeasuredheight ();} Setmeasureddimension (width, finalheight);}
3.2.2 Layout
@Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {super.onlayout (changed, L, T, R, b); LOGUTILS.D ("OnLayout mholder.moffsety=" + mholder.moffsety); mfootheight = Mfooterview.getmeasuredheight (); int ChildCount = Getchildcount (); int top = Getpaddingtop () + mholder.moffsety;for (int i = 0; i < ChildCount; i++) {View ch ILD = Getchildat (i); if (child = = Mheaderview) {//Headerview the effect of Headerview by moving the headerview upward by a distance from the height of an elevation child.layout (0, Top-mheaderviewheight,child.getmeasuredwidth (), top);} else {child.layout (0, Top, child.getmeasuredwidth (), child.getmeasuredheight () + top), top + + child.getmeasuredheight () ;}}}

which

int top = Getpaddingtop () + mholder.moffsety;
The mholder.moffsety is used to record the offset of the entire view in the y-axis direction. The reason for this is to add mholder.moffsety because the change in the view during the drag refresh will cause the system to re-measure and layout, plus this offset, you can keep the view current position when the system re-layout, do not revert to the original position.

3.2.3 Event handling and moving view

public boolean dispatchtouchevent (Motionevent ev) {final int action = motioneventcompat.getactionmasked (EV); int deltay = 0;switch (Action) {case MotionEvent.ACTION_DOWN:mHasSendCancelEvent = False;mhassenddownevent = False;mlasty = (int) Ev.getrawy (); minitialmotiony = Mlasty;if (!mscroller.isfinished () &&!mpullrefreshing &&! mpullloading) {mscroller.forcefinished (true);} Break;case MotionEvent.ACTION_MOVE:if (mpullloading | | mpullrefreshing | |!isenabled ()) {return Super.dispatchtouchevent (EV);} Mlastmoveevent = Ev;int currenty = (int) Ev.getrawy ();d Eltay = Currenty-mlasty;mlasty = currenty;//intercept the Motion Event only if user is not Scrollingif (!isintercepted && math.abs (DeltaY) < Mtouchslop) {isintercepted = True ; return super.dispatchtouchevent (EV);} LOGUTILS.D ("istop=" + mcontentview.istop () + "; isbottom=" + Mcontentview.isbottom ());d Eltay = (int) (deltay/offset_ RADIO); if (Mcontentview.istop () && (DeltaY > 0 | | (DeltaY < 0 &&Mholder.hasheaderpulldown ()))) {sendcancelevent (); Updateheaderheight (CurrentY, DeltaY);} else if ( Mcontentview.isbottom () && (DeltaY < 0 | | DeltaY > 0 && mholder.hasfooterpullup ())) { Sendcancelevent (); Updatefooterheight (DeltaY);} else if (mcontentview.istop () &&!mholder.hasheaderpulldown () | | mcontentview.isbottom () &&! Mholder.hasfooterpullup ()) {if (DeltaY > 0) senddownevent ();} Break;case MotionEvent.ACTION_CANCEL:case motionevent.action_up://if (mholder.moffsety! = 0 && Mrefreshviewlistener! = null//&&!mpullrefreshing &&!mpullloading) {// Mrefreshviewlistener.onrelease (mholder.moffsety);//}if (Mcontentview.istop () && Mholder.hasheaderpulldown ()) {//Invoke Refreshif (Menablepullrefresh && mholder.moffsety > Mheaderviewheight) {mpullrefreshing = true; Mheaderview.setstate (xrefreshviewstate.state_refreshing); if (mrefreshviewlistener! = null) { Mrefreshviewlistener.onrefresh ();}} Resetheaderheight ();} ELSE if (Mcontentview.isbottom () && Mholder.hasfooterpullup ()) {if (menablepullload) {int offset = 0-mholder.moff Sety-mfootheight;startscroll (offset, scroll_duration); Startloadmore ();} else {int offset = 0-mholder.moffsety;startscroll (offset, scroll_duration);}} Mlasty =-1; Resetminitialmotiony = 0;isintercepted = True;break;} return super.dispatchtouchevent (EV);}
As you can see, event handling is done in the dispatchtouchevent (motionevent ev) method, which was previously divided into two parts, in onintercepttouchevent (motionevent ev) method, event handling is performed in the ontouchevent (motionevent ev). This is done because the cannon said he pulled down when the refresh, because the child view is very complex, sub-view can sometimes preempt events, causing the card to not refresh. We all know that child view is available throughRequestdisallowintercepttouchevent to request the parent class not to intercept the event, thenOnintercepttouchevent method will not be executed, then we pull down the refresh is not reliable, so in order to solve this problem, I put all the processing into the Dispatchtouchevent method to do.

Look again at the two methods of Sendcancelevent () and Senddownevent ()

private void Sendcancelevent () {if (!mhassendcancelevent) {setrefreshtime (); Mhassendcancelevent = True;mhassenddownevent = false; Motionevent last = mlastmoveevent; Motionevent e = Motionevent.obtain (Last.getdowntime (), last.geteventtime () + viewconfiguration.getlongpresstimeout () , Motionevent.action_cancel, Last.getx (), Last.gety (), Last.getmetastate ());d Ispatchtoucheventsupper (e);}} private void Senddownevent () {if (!mhassenddownevent) {logutils.d ("senddownevent"); mhassendcancelevent = false; Mhassenddownevent = true;isintercepted = false;final Motionevent last = mlastmoveevent;if (last = = null) return; Motionevent e = Motionevent.obtain (Last.getdowntime (), Last.geteventtime (), Motionevent.action_down, Last.getX (), Last.gety (), Last.getmetastate ());d Ispatchtoucheventsupper (e);}} 
Touch event at the beginning of the quilt view will definitely receive, if it is a ListView, there will be item Click Effect appears, this is normal, but if the trigger drop refresh at this time, and also have the click effect of the item, then it looks not very natural, All this can be done by sendcancelevent () to send a cancel event to the child view so that the item's click Effect disappears. There is also when we pull down headerview after not reached the refresh condition, and then have to push the Headerview and completely hidden, at this time should I return the event to the child view, let the child view received the event and move, you can achieve the effect through senddownevent.

Finally, the mobile view processing

When the fingers are dragging,

public void Moveview (int deltay) {mholder.move (DeltaY); Mchild.offsettopandbottom (DeltaY); Mheaderview.offsettopandbottom (DeltaY); Mfooterview.offsettopandbottom (DeltaY); invalidate ();}
public int moffsety;public void move (int deltay) {moffsety + = DeltaY;}
Use the Moveview method to move the view and save the offset.

When the finger leaves, move the view through the scroller

Mscroller = new Scroller (GetContext (), New Linearinterpolator ());
A linear interpolator is used here to indicate that movement is a constant speed change.
/** *  * @param offsetY *            sliding offset, negative number upward slide, positive inverse * @param duration *            sliding duration */public void startscroll (int offsetY, in T duration) {mscroller.startscroll (0, mholder.moffsety, 0, OffsetY, duration); invalidate ();}
public void Computescroll () {super.computescroll (); if (Mscroller.computescrolloffset ()) {int lastscrolly = Mholder.moffsety;int currenty = Mscroller.getcurry (); int OffsetY = currenty-lastscrolly;lastscrolly = CurrentY; Moveview (OffsetY); LOGUTILS.D ("currenty=" + CurrentY + "; mholder.moffsety=" + mholder.moffsety);} else {LOGUTILS.D ("scroll end moffsety=" + Mholder.moffsety);}}
As can be seen from the above, only one moffsety variable is used to store the offset in the entire movement, and the code becomes very simple compared to the previous moment.

Iv. Final Notes

If you're interested in Xrefreshview, you can focus on GitHub Xrefreshview

and of course you can . Click here for direct download




Build Android Magnum pull-up dropdown refresh frame--xrefreshview (ii)

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.