用當前最流行的下拉刷新pullrefresh框架實現類似QQ的下拉刷新功能

用當前最流行的下拉刷新pullrefresh框架實現類似QQ的下拉刷新功能,下載地址爲:https://github.com/chrisbanes/Android-PullToRefresh

 

我先解釋一下下拉刷新涉及的過程:

1、  肯定要有一個下拉頭(下拉腳),在這個源碼裏面LoadingLayout作爲下拉頭的基類,你可以參照它已經實現的幾個樣式自定義自己的下拉頭,就是對裏面顯示的內容,動畫進行相應的修改。

2、  下拉的過程涉及幾個狀態,reset,pulltorefresh,refreshing,releasetorefresh等,對應的每個狀態分別有不同的動作,源碼裏面用IPullRefresh接口把相應的動作進行了聲明,我們只需要實現它就可以實現相應的動作。

3、  下拉的過程還涉及到下拉頭內容的變化,源碼中用ILoadingLayout接口對不同狀態下的下拉頭內容進行了封裝。

4、  源碼中最重要的基類是PullToRefreshBase,該類封裝了下拉刷新的整個過程的功能,但是該類是個抽象類,裏面有兩個抽象方法分別爲isReadyForPullEnd(),isReadyForPullStart();,這兩個方法主要是讓你根據自己情況進行下拉和上拉的判斷。該類也是一個泛型類,可以根據你傳入的視圖類型生成對應的刷新視圖。

5、  源碼中PullToRefreshAdapterViewBase類對PullToRefreshBase類進行了封裝,故名思議,主要是對AdapterView類型的刷新視圖進行的包裝,讓像ListView,GridView等繼承它實現起來更方便。

 

好了,回到主題,我發現該下拉刷新框架跟QQ的還是有所不一樣的,QQ的每次刷新成功都會在下拉頭進行提示,而這個刷新完直接回到了初始狀態,並沒有給出任何提示。

我的實現方法是:

1、在PullToRefreshBase類的內部枚舉類State中加了一個刷新成功的狀態,

public static enum State {

       /**

        *When the UI is in a state which means that user is not interacting

        *with the Pull-to-Refresh function.

        */

       RESET(0x0),

 

       /**

        *When the UI is being pulled by the user, but has not been pulled far

        *enough so that it refreshes when released.

        */

       PULL_TO_REFRESH(0x1),

 

       /**

        *When the UI is being pulled by the user, and <strong>has</strong>

        *been pulled far enough so that it will refresh when released.

        */

       RELEASE_TO_REFRESH(0x2),

 

       REFRESHING_SUCCEED(0x4),//此處是我加的狀態,命名可以隨意

       /**

        *When the UI is currently refreshing, caused by a pull gesture.

        */

       REFRESHING(0x8),

 

 

       /**

        *When the UI is currently refreshing, caused by a call to

        * {@link PullToRefreshBase#setRefreshing() setRefreshing()}.

        */

       MANUAL_REFRESHING(0x9),

 

       /**

        *When the UI is currently overscrolling, caused by a fling on the

        * RefreshableView.

        */

       OVERSCROLLING(0x10);

 

       /**

        *Maps an int to a specific state. This is needed when saving state.

        *

        * @param stateInt

        *           - int to map a State to

        * @return State thatstateInt maps to

        */

       static State mapIntToValue(final int stateInt) {

           for (State value : State.values()) {

              if (stateInt == value.getIntValue()) {

                  return value;

              }

           }

 

           // If not, returndefault

           return RESET;

       }

 

       private int mIntValue;

 

       State(int intValue) {

           mIntValue = intValue;

       }

 

       int getIntValue() {

           return mIntValue;

       }

    }

 

2、  既然有刷新成功這個狀態,肯定要有相關的操作,這裏我對ILoadingLayout,以及IPullRefresh進行了修改。

ILoadingLayout: 我添加了一個方法是對刷新成功內容標籤進行設置,

    public voidsetRefreshingCompleteLable(CharSequence completeLable);

IPullRefresh:我對之前的刷新完成方法進行了修改,通過調用者傳入一個變量判斷是否刷新成功。

原來的方法:public void onRefreshComplete();

現在的方法:public void setRefreshComplete(booleanisSucceed);

 

3、  通過修改2之後我們發現很多地方報錯,對的,我們這時只需要對報錯的地方進行相應的修改即可,這裏我們就要對下拉頭基類LoadingLayout進行相應的修改了。

(1)      添加了屬性刷新成功的字符,以及獲取它的資源值

private CharSequence mCompleteLable;

在構造方法中添加如下行,字符串資源值定義爲刷新成功

(2)      在該類我添加了如下方法:

   public final void refreshSucceed(){

      if (null != mHeaderText) {

         mHeaderText.setText(mCompleteLable);

      }

     

      refreshSucceedImpl();

   }

其中這個refreshSucceedImpl爲添加的抽象方法,用在具體下拉頭中實現。


(3)  分別找到這三個類,在裏面實現如下方法,主要用於對刷新成功下來頭的顯示。

   protected void refreshSucceedImpl() {

            mHeaderImage.clearAnimation();

            mHeaderImage.setVisibility(View.INVISIBLE);

            mHeaderProgress.setVisibility(View.GONE);

       }

4、  最後我們再來對PullToRefreshBase這個類進行最終的修改,就可以大功告成了。

在這個類中找到onfreshComplete()這個方法,我們改成這樣

@Override

public final void setRefreshComplete(booleanisSucceed) {

           if (isRefreshing()) {

                    if (isSucceed) {

                             setState(State.REFRESHING_SUCCEED);

                    } else {

                             setState(State.RESET);

                    }

           }

}

如果是刷新成功則,顯示刷新成功,如果是刷新失敗,我們直接回到初始狀態。

回到setState()方法,我們添加相應的改變


然後我們再去實現onRreshComplete()方法

protected void onRefreshComplete() {

           if(mShowViewWhileRefreshing){

                    switch (mCurrentMode) {

                    case PULL_FROM_END:

                             mFooterLayout.refreshSucceed();

                             break;

                    case PULL_FROM_START:

                             mHeaderLayout.refreshSucceed();

                             break;

                    default:

                             // NO-OP

                             break;

                    }

           }

           postDelayed(new Runnable() {

                   

                    @Override

                    public void run() {

                             setState(State.RESET);

                    }

           },500);

}

這裏注意一下,postDelayed主要用於顯示刷新成功之後回到初始狀態,時間設爲顯示時間,這裏我設的是500;

本來以爲大工告成,測試的時候發現了一個問題,每次刷新成功顯示完後,下拉頭的內容先回到初始狀態再滑到初始位置,這顯然不是我們想看到的,於是我對onreset方法進行了修改:

   /**

    * Called when the UI has been to be updated tobe in the

    * {@linkState#RESET} state.

    */

   protected void onReset() {

      mIsBeingDragged = false;

      mLayoutVisibilityChangesEnabled= true;

      //之前是這樣的:

      /**smoothScrollTo(0);

        *mHeaderLayout.reset();

         *  mFooterLayout.reset();*/

       //現在是這樣的,在滑動完成之後我們再對下拉內容進行初始化,這樣就看不到默認狀態了

      smoothScrollTo(0,newOnSmoothScrollFinishedListener() {

        

         @Override

         public voidonSmoothScrollFinished() {

            mHeaderLayout.reset();

            mFooterLayout.reset();

         }

      });

 

      // Always reset both layouts, just in case...

 

}

 

5、  我們在刷新完成的邏輯中調用setRefreshComplete(booleanisSucceed)這個方法即可,根據刷新的結果進行傳值,結果如下:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章