Open-source Android-PullToRefresh pull-down refresh source code analysis, androidpulltorefresh

Source: Internet
Author: User
Tags gety

Open-source Android-PullToRefresh pull-down refresh source code analysis, androidpulltorefresh

The PullToRefresh library is used at most. github mainly analyzes the source code implementation today.

We use the drop-down refresh of ListView for analysis, and the others are similar.

The parent View is LinearLayout, and Header View, Footer View, and ListView are added to LinearLayout.

PullToRefreshBase is the parent class that extends the horizontal layout of LinearLayout. If we use ListView, we need to watch the subclass PullToRefreshAdapterViewBase-> PullToRefreshListView.


The initialization code is in the PullToRefreshBase init method.

Key code:

// Refreshable View // By passing the attrs, we can add ListView/GridView params via XMLmRefreshableView = createRefreshableView (context, attrs); // View passed through subclass, addRefreshableView (context, mRefreshableView), such as ListView or ScrollView; // Add the view to the layout. // We need to create now layouts now creates the Header and Footer views. The default value is INVISIBLE, to add to the parent window mHeaderLayout = createLoadingLayout (context, Mode. PULL_FROM_START, a); mFooterLayout = createLoadingLayout (context, Mode. PULL_FROM_END, a); handleStyledAttributes (a); // Add the loadingView effect. Add the View to the ListView HeaderView to updateUIForMode (); // Add the layout to the parent View.

Protected void updateUIForMode () {final LinearLayout. layoutParams lp = getLoadingLayoutLayoutParams (); // Remove Header, and then 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, in fact, the padding method is used to set it to a negative value, and it will be out on 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 two loadingviews. One is added to LinearLayout, and the other is added to the Header of ListView.

Look at the handleStyledAttributes method to locate the sub-class rewrite.

FrameLayout frame = new FrameLayout (getContext ());
MHeaderLoadingView = createLoadingLayout (getContext (), Mode. PULL_FROM_START, );
MHeaderLoadingView. setVisibility (View. GONE );
Frame. addView (mHeaderLoadingView, lp );
MRefreshableView. addHeaderView (frame, null, false); // Add LoadingView to ListView Header

// HeaderView a total of two loadingviews. One is added to LinearLayout and the other is added to the HeaderView of ListView.
The addViewInternal method is added to the LinearLayout parent class.


Let's take a look at LoadingLayout. There are two types of FlipLoadingLayout and RotateLoadingLayout. Generally, we use rotation to load the animation.
A rotating image on the left and a text and time prompt on the right

The first LoadingLayout mainly displays: pull-down refresh, release to refresh
The second LoadingLayout displays the loose text: loading...

The structure is as follows:



When the UI is initialized, let's take a look at the onTouch drop-down capture event.


Public final boolean onTouchEvent (MotionEvent event) {if (! IsPullToRefreshEnabled () {return false;} // If we're 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 (); pullEvent (); // start the drop-down and move return true;} break;} case MotionEvent. ACTION_DOWN: {if (isReadyForPull () {// press start to drop down mLastMotionY = mInitialMotionY = event. getY (); mLastMotionX = mInitialMotionX = event. getX (); return true;} break;} case MotionEvent. ACTION_CAN CEL: case MotionEvent. ACTION_UP: {// if (mIsBeingDragged) {mIsBeingDragged = false; if (mState = State. RELEASE_TO_REFRESH & (null! = MOnRefreshListener | null! = MOnRefreshListener2) {setState (State. REFRESHING, true); // put down your finger to start the callback and execute our callback task return true;} // If we're re already refreshing, just scroll back to the topif (isRefreshing () {smoothScrollTo (0); return true;} // If we haven't returned by here, then we're not in a state // to pull, so just resetsetState (State. RESET); // restore to the original UI status return true;} break ;}} return false ;}


Look at the pullEvent method private void pullEvent () {final int newScrollValue; final int itemDimension; final float initialMotionValue, lastMotionValue; switch (inflow () {case HORIZONTAL: initialMotionValue = inflow; lastMotionValue = mLastMotionX; break; case VERTICAL: default: initialMotionValue = mInitialMotionY; lastMotionValue = mLastMotionY; break ;}// calculates the number of switches moved by the drop-down list ){ 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;} // display the Moving Value of HeaderView, so that LoadingView can display setHeaderScroll (newScrollValue ); if (newScrollVa Lue! = 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 loaded image on the left to display the text and image. This part will eventually execute the onPullImpl method break in LoadingLayout;} // The update status includes 2 releasing the press touch, also, if (mState! = State. PULL_TO_REFRESH & itemDimension> = Math. abs (newScrollValue) {setState (State. PULL_TO_REFRESH);} else if (mState = State. PULL_TO_REFRESH & itemDimension <Math. abs (newScrollValue) {setState (State. RELEASE_TO_REFRESH); // The drop-down loose can be removed }}}



Let's take a look at the setHeaderScroll Method Code protected final void setHeaderScroll (int value) {if (DEBUG) {Log. d (LOG_TAG, "setHeaderScroll:" + value) ;}if (DEBUG) {Log. d (LOG_TAG, "setHeaderScroll:" + value);} // Clamp value to with pull scroll rangefinal int maximumPullScroll = getMaximumPullScroll (); value = Math. min (maximumPullScroll, Math. max (-maximumPullScroll, value); if (mLayoutVisibilityChangesEnabled) {if (value <0) {// mHeaderLayout is displayed only when there is a shift. setVisibility (View. VISIBLE);} else if (value> 0) {<span style = "font-family: Arial, Helvetica, sans-serif; "> // displayed only when there is a displacement </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 wowould negate any HW layer performance boost. */ViewCompat. setLayerType (mRefreshableViewWrapper, value! = 0? View. LAYER_TYPE_HARDWARE: View. LAYER_TYPE_NONE);} // return to the most common mobile Layout switch (getPullToRefreshScrollDirection () {case VERTICAL: scrollTo (0, value); break; case HORIZONTAL: scrollTo (value, 0); break ;}}

SetState (State. REFRESHING, true); // pull down the top loose and execute the onRefreshing method. The task interface implemented by callback is OnRefreshListener.


Protected void onRefreshing (final boolean doScroll) {if (mMode. showHeaderLoadingLayout () {mHeaderLayout. refreshing ();} if (mMode. showFooterLoadingLayout () {mFooterLayout. refreshing ();} if (doScroll) {if (rollback) {// Call Refresh Listener when the Scroll has listener Listener = new listener () {@ Overridepublic void onSmoothScrollFinished () {callRefreshListener (); // callback interface execution}; switch (mCurrentMode) {case when: case PULL_FROM_END: smoothScrollTo (getFooterSize (), listener); break; default: case PULL_FROM_START: smoothScrollTo (-getHeaderSize (), listener); break ;}} else {smoothScrollTo (0); // return to the original location} 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 where both the pull-up and drop-down operations are acceptable. Use onRefreshListener2if (mCurrentMode = Mode. PULL_FROM_START) {mOnRefreshListener2.onPullDownToRefresh (this);} else if (mCurrentMode = Mode. PULL_FROM_END) {mOnRefreshListener2.onPullUpToRefresh (this );}}}

Summary: The status includes pull-down refresh, loose refresh, refreshing, and Loading hiding. The most basic code of scrollTo is used for mobile UI. For the animation part, you can view the two subclasses of LoadingLayout.

There are still many details that have not been analyzed. If you have any questions, thank you.



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.