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

Source: Internet
Author: User
Tags gety


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

Build Android Magnum Pull-up drop-down refresh frame--xrefreshview (iii)


First, preface

Since the last published build Android Magnum pull down refresh frame--xrefreshview (i), the period of the great half month has been very busy. But every night after work I have in the update and maintenance of Xrefreshview, but also based on some friends of the views of some of the problems to overcome, this time the reason to write this article. is due to the fact that Xrefreshview has reached a stage of relatively reliable and stable function. Below I will introduce the latest features and how to use the Xrefreshview. And the main idea of implementation.

Second, update

2.1 Infer the change in the timing of pull-up pull-up

Before is through Refreshview.setrefreshviewtype (xrefreshviewtype.abslistview); This lets you pre-set the type of view to select the appropriate method to infer the timing. Now it is not necessary to do so, to change 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;} /** * is used to infer whether the view can slide 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 infer whether a view can slide up or down to infer that the view has reached the top or bottom. After 4.0 in a method is generally very useful. But 2.3.3 once was not so, in order to be compatible with 2.3.3 I did some of the view type inference. A method that provides a special inference to the top or bottom through the type of view. Under normal circumstances, frequently used view can be accurately inferred from the above method is not to reach the top or bottom, but suppose you want to refresh is a complex or your own definition of view, can also be done in the following way
Refreshview.setontoprefreshtime (New Ontoprefreshtime () {@Overridepublic Boolean istop () {return Stickylv.getfirstvisibleposition () = = 0;}}); Refreshview.setonbottomloadmoretime (New Onbottomloadmoretime () {@Overridepublic Boolean isbottom () {return Stickylv.getlastvisibleposition () = = MTotalItemCount-1;}});

Xrefreshview put the inference view to the top and bottom of the work to you to do, you just tell Xrefreshview when is the right time to refresh, and the last blog mentioned in the method is different, Xrefreshview provides two interfaces this time, separating the inference time between the top and bottom. The main consideration is that the drop-down refresh and pull-up loading are not required at all.

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

At the beginning, 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 that implements animation effects. With the Honeycomb API, you can achieve very complex animations, but assuming that developers want to use this set of APIs under 3.0, you need to use the open source framework nine old androids, which infers its SDK version number based on the machine we're executing. Assume that the API3.0 above uses an animated class that comes with Android, otherwise use the nine old androids library. This is a compatible library. (Note: The red part of the word I was directly quoted Xiahanming the original blog of the Great God, has been watching his blog. So always admired him very much. The quality of his blog is very good. After that, the problem of compatibility is handled even better. But later Xutils 4 group of Artillery told me, Xrefreshview in the drop when there will be jitter, I know this situation after the start to find problems, and later found that is due to the use of property animation to move the header of the problem, without the property animation is good. Think carefully. Property animations are actually run by reflection to attribute the corresponding Get/set method, after all reflection. And when the finger moves, it triggers a lot of action_move. Every action_move will do a reflection, then will do a lot of reflection work, a large number of intensive reflection will lead to a decrease in performance, so there is a situation of jitter. After giving up reflection, I used this method of View.offsettopandbottom (DeltaY). Look at the gaze 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. Very easy to use, you deserve to have.

The 2.3demo has a flow-through layout

Very easy, interested in being able to see


2.4 Click button Refresh and Support rebound

Now with 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 loading
Sets whether the pull-down refresh refreshview.setpullrefreshenable (false) is sufficient, or whether the setting can be loaded into refreshview.setpullloadenable (false);
The cannon said it would be good to have the rebound effect if it could not pull the refresh and pull up, so now the version number is supported.

III. realization of relevant
3.1 Changes before and after

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

/** * At the beginning of loading a lot of other time, record the Childview start of the y-coordinate */private float Mchildy = -1;/** * At the beginning of loading many other times, record the footview of the beginning of the y-axis coordinates */ private float Mfooty = -1;/** * At the beginning of loading a lot of other time, recorded the Headview the beginning of the Y coordinate */private float mheady =-1;
It then constantly updates the y-coordinate of the current view while the finger is moving. Finally, to move the individual view, this inadvertently increased the workload and the complexity of the work, then I thought of the three parts as a whole. This has been a lot simpler. There is no need for so many variables.


3.2 Implementation Process

3.2.1 Measurements

/* * Measure the width and height of the view. Width is the width set by the user. The height of the 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 () ;}}}

Of

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. is because the change in the view during the drag refresh will cause the system to measure and layout again, plus this offset. The ability to keep the view current position while the system is being laid out again. Do not revert to the initial 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);}
The first thing you can see is that the event handling is done in the dispatchtouchevent (motionevent ev) method, which was previously divided into two parts. Intercept in the 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 the child view is able to request the parent class to not intercept the event through Requestdisallowintercepttouchevent, then the Onintercepttouchevent method will not run. Then we are not reliable to pull the refresh, so in order to solve the 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 events will definitely be received at the beginning of Quilt view. If it is a ListView, there will be the click effect of the item appears, which is very normal, but assume that the trigger drop refresh, at the same time there is an item click Effect, then it does not look very natural, all at this time can pass sendcancelevent () To send a cancel event to the child view. The Click effect of this item disappears. And when we pull down the headerview after not to reach the refresh condition, and then have to push the Headerview and completely hidden, this time should I return the event to the child view. Let the child view receive the event and move, 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 offsets.

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, int 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, the entire moving process uses only a moffsety variable to store the offset, and the code becomes very easy compared to the previous moment.

Iv. Final Notes

Let's say you're interested in Xrefreshview. Be able to focus on Xrefreshview on GitHub

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.