1. 程式人生 > >Android 下拉重新整理框架實現

Android 下拉重新整理框架實現

前段時間專案中用到了下拉重新整理功能,之前在網上也找到過類似的demo,但這些demo的質量參差不齊,使用者體驗也不好,介面設計也不行。最張沒辦法,終於忍不了了,自己就寫了一個下拉重新整理的框架,這個框架是一個通用的框架,效果和設計感覺都還不錯,現在分享給各位看官。

致謝:

1. 感謝lk6233160同學提出的問題,旋轉View時呼叫setRotation方法只能是在API Level11(3.0)以上才能用,這個問題的解決辦法是給ImageView設定一個Matrix,把Matrix上面作用一個旋轉矩陣,但是如果不是ImageView的話,可能實現起來比較麻煩,再次謝謝lk6233160同學。

2. 謝謝

如毛毛風提出的問題,向下滑動後,再向上滑動到頭,只能再鬆手後才能再次下拉。這個問題的回覆請參考評論。

技術交流群:

QQ:197990971(人員已滿)

1. 關於下拉重新整理

下拉重新整理這種使用者互動最早由twitter創始人洛倫•布里切特(Loren Brichter)發明,有理論認為,下拉重新整理是一種適用於按照從新到舊的時間順序排列feeds的應用,在這種應用場景中看完舊的內容時,使用者會很自然地下拉查詢更新的內容,因此下拉重新整理就顯得非常合理。大家可以參考這篇文章:有趣的下拉重新整理,下面我貼出一個有趣的下拉重新整理的案例。
圖一、有趣的下拉重新整理案例(一)
圖一、有趣的下拉重新整理案例(二)

2. 實現原理

上面這些例子,外觀做得再好看,他的本質上都一樣,那就是一個下拉重新整理控制元件通常由以下幾部分組成: 【1】Header Header通常有下拉箭頭,文字,進度條等元素,根據下拉的距離來改變它的狀態,從而顯示不同的樣式 【2】Content 這部分是內容區域,網上有很多例子都是直接在ListView裡面新增Header,但這就有侷限性,因為好多情況下並不一定是用ListView來顯示資料。我們把要顯示內容的View放置在我們的一個容器中,如果你想實現一個用ListView顯示資料的下拉重新整理,你需要建立一個ListView旋轉到我的容器中。我們處理這個容器的事件(down, move, up),如果向下拉,則把整個佈局向下滑動,從而把header顯示出來。 【3】Footer
Footer可以用來顯示向上拉的箭頭,自動載入更多的進度條等。 以上三部分總結的說來,就是如下圖所示的這種佈局結構: 圖三,下拉重新整理的佈局結構 關於上圖,需要說明幾點: 1、這個佈局擴充套件於LinearLayout,垂直排列 2、從上到下的順序是:Header, Content, Footer 3、Content填充滿父控制元件,通過設定top, bottom的padding來使Header和Footer不可見,也就是讓它超出螢幕外 4、下拉時,呼叫scrollTo方法來將整個佈局向下滑動,從而把Header顯示出來,上拉正好與下拉相反。 5、派生類需要實現的是:將Content View填充到父容器中,比如,如果你要使用的話,那麼你需要把ListView, ScrollView, WebView等新增到容器中。 6、上圖中的紅色區域就是屏的大小(嚴格來說,這裡說螢幕大小並不準確,應該說成內容區域更加準確)

3. 具體實現

明白了實現原理與過程,我們嘗試來具體實現,首先,為了以後更好地擴充套件,設計更加合理,我們把下拉重新整理的功能抽象成一個介面:

1、IPullToRefresh<T extends View>

它具體的定義方法如下: [java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. publicinterface IPullToRefresh<T extends View> {  
  2.     publicvoid setPullRefreshEnabled(boolean pullRefreshEnabled);  
  3.     publicvoid setPullLoadEnabled(boolean pullLoadEnabled);  
  4.     publicvoid setScrollLoadEnabled(boolean scrollLoadEnabled);  
  5.     publicboolean isPullRefreshEnabled();  
  6.     publicboolean isPullLoadEnabled();  
  7.     publicboolean isScrollLoadEnabled();  
  8.     publicvoid setOnRefreshListener(OnRefreshListener<T> refreshListener);  
  9.     publicvoid onPullDownRefreshComplete();  
  10.     publicvoid onPullUpRefreshComplete();  
  11.     public T getRefreshableView();  
  12.     public LoadingLayout getHeaderLoadingLayout();  
  13.     public LoadingLayout getFooterLoadingLayout();  
  14.     publicvoid setLastUpdatedLabel(CharSequence label);  
  15. }  
public interface IPullToRefresh<T extends View> {
    public void setPullRefreshEnabled(boolean pullRefreshEnabled);
    public void setPullLoadEnabled(boolean pullLoadEnabled);
    public void setScrollLoadEnabled(boolean scrollLoadEnabled);
    public boolean isPullRefreshEnabled();
    public boolean isPullLoadEnabled();
    public boolean isScrollLoadEnabled();
    public void setOnRefreshListener(OnRefreshListener<T> refreshListener);
    public void onPullDownRefreshComplete();
    public void onPullUpRefreshComplete();
    public T getRefreshableView();
    public LoadingLayout getHeaderLoadingLayout();
    public LoadingLayout getFooterLoadingLayout();
    public void setLastUpdatedLabel(CharSequence label);
}
這個介面是一個泛型的,它接受View的派生類,因為要放到我們的容器中的不就是一個View嗎?
2、PullToRefreshBase<T extends View>
這個類實現了IPullToRefresh介面,它是從LinearLayout繼承過來,作為下拉重新整理的一個抽象基類,如果你想實現ListView的下拉重新整理,只需要擴充套件這個類,實現一些必要的方法就可以了。這個類的職責主要有以下幾點:
  • 處理onInterceptTouchEvent()和onTouchEvent()中的事件當內容的View(比如ListView)正如處於最頂部,此時再向下拉,我們必須截斷事件,然後move事件就會把後續的事件傳遞到onTouchEvent()方法中,然後再在這個方法中,我們根據move的距離再進行scroll整個View。
  • 負責建立Header、Footer和Content View在構造方法中呼叫方法去建立這三個部分的View,派生類可以重寫這些方法,以提供不同式樣的Header和Footer,它會呼叫createHeaderLoadingLayout和createFooterLoadingLayout方法來建立Header和Footer建立Content View的方法是一個抽象方法,必須讓派生類來實現,返回一個非null的View,然後容器再把這個View新增到自己裡面。
  • 設定各種狀態:這裡面有很多狀態,如下拉、上拉、重新整理、載入中、釋放等,它會根據使用者拉動的距離來更改狀態,狀態的改變,它也會把Header和Footer的狀態改變,然後Header和Footer會根據狀態去顯示相應的介面式樣。
3、PullToRefreshBase<T extends View>繼承關係 這裡我實現了三個下拉重新整理的派生類,分別是ListView、ScrollView、WebView三個,它們的繼承關係如下:
圖四、PullToRefreshBase類的繼承關係 關於PullToRefreshBase類及其派和類,有幾點需要說明:
  • 對於ListView,ScrollView,WebView這三種情況,他們是否滑動到最頂部或是最底部的實現是不一樣的,所以,在PullToRefreshBase類中需要呼叫兩個抽象方法來判斷當前的位置是否在頂部或底部,而其派生類必須要實現這兩個方法。比如對於ListView,它滑動到最頂部的條件就是第一個child完全可見並且first postion是0。這兩個抽象方法是:
[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. /** 
  2.  * 判斷重新整理的View是否滑動到頂部 
  3.  *  
  4.  * @return true表示已經滑動到頂部,否則false 
  5.  */
  6. protectedabstractboolean isReadyForPullDown();  
  7. /** 
  8.  * 判斷重新整理的View是否滑動到底 
  9.  *  
  10.  * @return true表示已經滑動到底部,否則false 
  11.  */
  12. protectedabstractboolean isReadyForPullUp();  
    /**
     * 判斷重新整理的View是否滑動到頂部
     * 
     * @return true表示已經滑動到頂部,否則false
     */
    protected abstract boolean isReadyForPullDown();
    
    /**
     * 判斷重新整理的View是否滑動到底
     * 
     * @return true表示已經滑動到底部,否則false
     */
    protected abstract boolean isReadyForPullUp();
  • 建立可下拉重新整理的View(也就是content view)的抽象方法是
[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. /** 
  2.  * 建立可以重新整理的View 
  3.  *  
  4.  * @param context context 
  5.  * @param attrs 屬性 
  6.  * @return View 
  7.  */
  8. protectedabstract T createRefreshableView(Context context, AttributeSet attrs);  
    /**
     * 建立可以重新整理的View
     * 
     * @param context context
     * @param attrs 屬性
     * @return View
     */
    protected abstract T createRefreshableView(Context context, AttributeSet attrs);
4、LoadingLayout LoadingLayout是重新整理Layout的一個抽象,它是一個抽象基類。Header和Footer都擴充套件於這個類。這類抽象類,提供了兩個抽象方法:
  • getContentSize
這個方法返回當前這個重新整理Layout的大小,通常返回的是佈局的高度,為了以後可以擴充套件為水平拉動,所以方法名字沒有取成getLayoutHeight()之類的,這個返回值,將會作為鬆手後是否可以重新整理的臨界值,如果下拉的偏移值大於這個值,就認為可以重新整理,否則不重新整理,這個方法必須由派生類來實現。
  • setState
這個方法用來設定當前重新整理Layout的狀態,PullToRefreshBase類會呼叫這個方法,當進入下拉,鬆手等動作時,都會呼叫這個方法,派生類裡面只需要根據這些狀態實現不同的介面顯示,如下拉狀態時,就顯示出箭頭,重新整理狀態時,就顯示loading的圖示。 可能的狀態值有:RESET, PULL_TO_REFRESH, RELEASE_TO_REFRESH, REFRESHING, NO_MORE_DATA

LoadingLayout及其派生類的繼承關係如下圖所示:

圖五、LoadingLayout及其派生類的類圖 我們可以隨意地制定自己的Header和Footer,我們也可以實現如圖一和圖二中顯示的各種下拉重新整理案例中的Header和Footer,只要重寫上述兩個方法getContentSize()和setState()就行了。HeaderLoadingLayout,它預設是顯示箭頭式樣的佈局,而RotateLoadingLayout則是顯示一個旋轉圖示的式樣。 5、事件處理 我們必須重寫PullToRefreshBase類的兩個事件相關的方法onInterceptTouchEvent()和onTouchEvent()方法。由於ListView,ScrollView,WebView它們是放到PullToRefreshBase內部的,所在事件先是傳遞到PullToRefreshBase#onInterceptTouchEvent()方法中,所以我們應該在這個方法中去處理ACTION_MOVE事件,判斷如果當前ListView,ScrollView,WebView是否在最頂部或最底部,如果是,則開始截斷事件,一旦事件被截斷,後續的事件就會傳遞到PullToRefreshBase#onInterceptTouchEvent()方法中,我們再在ACTION_MOVE事件中去移動整個佈局,從而實現下拉或上拉動作。 6、滾動佈局(scrollTo) 如圖三的佈局結構可知,預設情況下Header和Footer是放置在Content View的最上面和最下面,通過設定padding來讓他跑到螢幕外面去了,如果我們將整個佈局向下滾動(scrollTo)一定距離,那麼Header就會被顯示出來,基於這種情況,所以在我的實現中,最終我是呼叫scrollTo來實現下拉動作的。 總的說來,實現的重要的點就這些,具體的一些細節在實現在會碰到很多,可以參考程式碼。

4. 如何使用

使用下拉重新整理的程式碼如下 [java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. @Override
  2.     publicvoid onCreate(Bundle savedInstanceState) {  
  3.         super.onCreate(savedInstanceState);  
  4.         mPullListView = new PullToRefreshListView(this);  
  5.         setContentView(mPullListView);  
  6.         // 上拉載入不可用
  7.         mPullListView.setPullLoadEnabled(false);  
  8.         // 滾動到底自動載入可用
  9.         mPullListView.setScrollLoadEnabled(true);  
  10.         mCurIndex = mLoadDataCount;  
  11.         mListItems = new LinkedList<String>();  
  12.         mListItems.addAll(Arrays.asList(mStrings).subList(0, mCurIndex));  
  13.         mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);  
  14.         // 得到實際的ListView
  15.         mListView = mPullListView.getRefreshableView();  
  16.         // 繫結資料
  17.         mListView.setAdapter(mAdapter);         
  18.         // 設定下拉重新整理的listener
  19.         mPullListView.setOnRefreshListener(new OnRefreshListener<ListView>() {  
  20.             @Override
  21.             publicvoid onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {  
  22.                 mIsStart = true;  
  23.                 new GetDataTask().execute();  
  24.             }  
  25.             @Override
  26.             publicvoid onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {  
  27.                 mIsStart = false;  
  28.                 new GetDataTask().execute();  
  29.             }  
  30.         });  
  31.         setLastUpdateTime();  
  32.         // 自動重新整理
  33.         mPullListView.doPullRefreshing(true500);  
  34.     }  
@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        mPullListView = new PullToRefreshListView(this);
        setContentView(mPullListView);
        
        // 上拉載入不可用
        mPullListView.setPullLoadEnabled(false);
        // 滾動到底自動載入可用
        mPullListView.setScrollLoadEnabled(true);
        
        mCurIndex = mLoadDataCount;
        mListItems = new LinkedList<String>();
        mListItems.addAll(Arrays.asList(mStrings).subList(0, mCurIndex));
        mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);
        
        // 得到實際的ListView
        mListView = mPullListView.getRefreshableView();
        // 繫結資料
        mListView.setAdapter(mAdapter);       
        // 設定下拉重新整理的listener
        mPullListView.setOnRefreshListener(new OnRefreshListener<ListView>() {
            @Override
            public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
                mIsStart = true;
                new GetDataTask().execute();
            }

            @Override
            public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
                mIsStart = false;
                new GetDataTask().execute();
            }
        });
        setLastUpdateTime();
        
        // 自動重新整理
        mPullListView.doPullRefreshing(true, 500);
    }
這是初始化一個下拉重新整理的佈局,並且呼叫setContentView來設定到Activity中。 在下拉重新整理完成後,我們可以呼叫onPullDownRefreshComplete()和onPullUpRefreshComplete()方法來停止重新整理和載入

5. 執行效果

這裡列出了demo的執行效果圖。
圖六、ListView下拉重新整理,注意Header和Footer的樣式
圖七、WebView和ScrollView的下拉重新整理效果圖

6. 原始碼下載

實現這個下拉重新整理的框架,並不是我的原創,我也是參考了很多開源的,把我認為比較好的東西借鑑過來,從而形成我的東西,我主要是參考了下面這個demo: https://github.com/chrisbanes/Android-PullToRefresh 這個demo寫得不錯,不過他這個太複雜了,我們都知道,一旦複雜了,萬一我們要新增一些需要,自然也要費勁一些,我其實就是把他的簡化再簡化,以滿足我們自己的需要。 轉載請說明出處 謝謝!!!

7. Bug修復

已知bug修復情況如下,發現了程式碼bug的看官也可以給我反饋,謝謝~~~ 1,對於ListView的下拉重新整理,當啟用滾動到底自動載入時,如果footer由隱藏變為顯示時,出現顯示異常的情況 這個問題已經修復了,修正的程式碼如下:
  • PullToRefreshListView#setScrollLoadEnabled方法,修正後的程式碼如下:
[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. @Override
  2. publicvoid setScrollLoadEnabled(boolean scrollLoadEnabled) {  
  3.     if (isScrollLoadEnabled() == scrollLoadEnabled) {  
  4.         return;  
  5.     }  
  6.     super.setScrollLoadEnabled(scrollLoadEnabled);  
  7.     if (scrollLoadEnabled) {  
  8.         // 設定Footer
  9.         if (null == mLoadMoreFooterLayout) {  
  10.             mLoadMoreFooterLayout = new FooterLoadingLayout(getContext());  
  11.             mListView.addFooterView(mLoadMoreFooterLayout, nullfalse);  
  12.         }  
  13.         mLoadMoreFooterLayout.show(true);  
  14.     } else {  
  15.         if (null != mLoadMoreFooterLayout) {  
  16.             mLoadMoreFooterLayout.show(false);  
  17.         }  
  18.     }  
  19. }  
    @Override
    public void setScrollLoadEnabled(boolean scrollLoadEnabled) {
        if (isScrollLoadEnabled() == scrollLoadEnabled) {
            return;
        }
        
        super.setScrollLoadEnabled(scrollLoadEnabled);
        
        if (scrollLoadEnabled) {
            // 設定Footer
            if (null == mLoadMoreFooterLayout) {
                mLoadMoreFooterLayout = new FooterLoadingLayout(getContext());
                mListView.addFooterView(mLoadMoreFooterLayout, null, false);
            }
            
            mLoadMoreFooterLayout.show(true);
        } else {
            if (null != mLoadMoreFooterLayout) {
                mLoadMoreFooterLayout.show(false);
            }
        }
    }
  • LoadingLayout#show方法,修正後的程式碼如下:
[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. /** 
  2.  * 顯示或隱藏這個佈局 
  3.  *  
  4.  * @param show flag 
  5.  */
  6. publicvoid show(boolean show) {  
  7.     // If is showing, do nothing.
  8.     if (show == (View.VISIBLE == getVisibility())) {  
  9.         return;  
  10.     }  
  11.     ViewGroup.LayoutParams params = mContainer.getLayoutParams();  
  12.     if (null != params) {  
  13.         if (show) {  
  14.             params.height = ViewGroup.LayoutParams.WRAP_CONTENT;  
  15.         } else {  
  16.             params.height = 0;  
  17.         }  
  18.         requestLayout();  
  19.         setVisibility(show ? View.VISIBLE : View.INVISIBLE);  
  20.     }  
  21. }  
    /**
     * 顯示或隱藏這個佈局
     * 
     * @param show flag
     */
    public void show(boolean show) {
        // If is showing, do nothing.
        if (show == (View.VISIBLE == getVisibility())) {
            return;
        }
        
        ViewGroup.LayoutParams params = mContainer.getLayoutParams();
        if (null != params) {
            if (show) {
                params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
            } else {
                params.height = 0;
            }
            
            requestLayout();
            setVisibility(show ? View.VISIBLE : View.INVISIBLE);
        }
    }
在更改LayoutParameter後,呼叫requestLayout()方法。
  • 圖片旋轉相容2.x系統
我之前想的是這個只需要相容3.x以上的系統,但發現有很多網友在使用過程中遇到過相容性問題,這次抽空將這個相容性一併實現了。        onPull的修改如下:
[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. @Override
  2. publicvoid onPull(float scale) {  
  3.     if (null == mRotationHelper) {  
  4.         mRotationHelper = new ImageViewRotationHelper(mArrowImageView);  
  5.     }  
  6.     float angle = scale * 180f; // SUPPRESS CHECKSTYLE
  7.     mRotationHelper.setRotation(angle);  
  8. }  
    @Override
    public void onPull(float scale) {
        if (null == mRotationHelper) {
            mRotationHelper = new ImageViewRotationHelper(mArrowImageView);
        }
        
        float angle = scale * 180f; // SUPPRESS CHECKSTYLE
        mRotationHelper.setRotation(angle);
    }

ImageViewRotationHelper主要的作用就是實現了ImageView的旋轉功能,內部作了版本的區分,實現程式碼如下:
[java] view plain copy print?在CODE上檢視程式碼片派生到我的程式碼片
  1. /** 
  2.      * The image view rotation helper 
  3.      *  
  4.      * @author lihong06 
  5.      * @since 2014-5-2 
  6.      */
  7.     staticclass ImageViewRotationHelper {  
  8.         /** The imageview */
  9.         privatefinal ImageView mImageView;  
  10.         /** The matrix */
  11.         private Matrix mMatrix;  
  12.         /** Pivot X */
  13.         privatefloat mRotationPivotX;  
  14.         /** Pivot Y */
  15.         privatefloat mRotationPivotY;  
  16.         /** 
  17.          * The constructor method. 
  18.          *  
  19.          * @param imageView the image view 
  20.          */
  21.         public ImageViewRotationHelper(ImageView imageView) {  
  22.             mImageView = imageView;  
  23.         }  
  24.         /** 
  25.          * Sets the degrees that the view is rotated around the pivot point. Increasing values 
  26.          * result in clockwise rotation. 
  27.          * 
  28.          * @param rotation The degrees of rotation. 
  29.          * 
  30.          * @see #getRotation() 
  31.          * @see #getPivotX() 
  32.          * @see #getPivotY() 
  33.          * @see #setRotationX(float) 
  34.          * @see #setRotationY(float) 
  35.          * 
  36.          * @attr ref android.R.styleable#View_rotation 
  37.          */
  38.         publicvoid setRotation(float rotation) {  
  39.             if (APIUtils.hasHoneycomb()) {  
  40.                 mImageView.setRotation(rotation);  
  41.             } else {  
  42.                 if (null == mMatrix) {  
  43.                     mMatrix = new Matrix();  
  44.                     // 計算旋轉的中心點
  45.                     Drawable imageDrawable = mImageView.getDrawable();  
  46.                     if (null != imageDrawable) {  
  47.                         mRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f);  
  48.                         mRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f);  
  49.                     }  
  50.                 }  
  51.                 mMatrix.setRotate(rotation, mRotationPivotX, mRotationPivotY);  
  52.                 mImageView.setImageMatrix(mMatrix);  
  53.             }  
  54.         }  
  55.     }  
/**
     * The image view rotation helper
     * 
     * @author lihong06
     * @since 2014-5-2
     */
    static class ImageViewRotationHelper {
        /** The imageview */
        private final ImageView mImageView;
        /** The matrix */
        private Matrix mMatrix;
        /** Pivot X */
        private float mRotationPivotX;
        /** Pivot Y */
        private float mRotationPivotY;
        
        /**
         * The constructor method.
         * 
         * @param imageView the image view
         */
        public ImageViewRotationHelper(ImageView imageView) {
            mImageView = imageView;
        }
        
        /**
         * Sets the degrees that the view is rotated around the pivot point. Increasing values
         * result in clockwise rotation.
         *
         * @param rotation The degrees of rotation.
         *
         * @see #getRotation()
         * @see #getPivotX()
         * @see #getPivotY()
         * @see #setRotationX(float)
         * @see #setRotationY(float)
         *
         * @attr ref android.R.styleable#View_rotation
         */
        public void setRotation(float rotation) {
            if (APIUtils.hasHoneycomb()) {
                mImageView.setRotation(rotation);
            } else {
                if (null == mMatrix) {
                    mMatrix = new Matrix();
                    
                    // 計算旋轉的中心點
                    Drawable imageDrawable = mImageView.getDrawable();
                    if (null != imageDrawable) {
                        mRotationPivotX = Math.round(imageDrawable.getIntrinsicWidth() / 2f);
                        mRotationPivotY = Math.round(imageDrawable.getIntrinsicHeight() / 2f);
                    }
                }
                
                mMatrix.setRotate(rotation, mRotationPivotX, mRotationPivotY);
                mImageView.setImageMatrix(mMatrix);
            }
        }
    }
最核心的就是,如果在2.x的版本上,旋轉ImageView使用Matrix。
  • PullToRefreshBase構造方法相容2.x
在三個引數的構造方法宣告如下標註:     @SuppressLint("NewApi")
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
大家如果還有什麼問題,歡迎留言~~~

相關推薦

Android 重新整理框架實現

前段時間專案中用到了下拉重新整理功能,之前在網上也找到過類似的demo,但這些demo的質量參差不齊,使用者體驗也不好,介面設計也不行。最張沒辦法,終於忍不了了,自己就寫了一個下拉重新整理的框架,這個框架是一個通用的框架,效果和設計感覺都還不錯,現在分享給各位看官。 致謝: 1. 感謝lk6233160同學

Android重新整理框架大集合

本篇主要是記錄了下網路上流行的下拉重新整理的框架,主要介紹Android智慧下拉重新整理框架-SmartRefreshLayout。 作者孜孜不倦的維護令我等後輩們躺著也能吃到雞 後續將

解讀Google官方SwipeRefreshLayout控制元件原始碼,帶你揭祕Android重新整理實現原理

前言 想必大家也發現,時下的很多App都應用了這個Google出品的SwipeRefreshLayout下拉重新整理控制元件,它以Material Design風格、適用場景廣泛,簡單易用等特性而獨步江湖。但在我們使用的過程中,不可避免地會發現一些bug,或者

Android重新整理完全解析 教你如何一分鐘實現重新整理功能

                最近專案中需要用到ListView下拉重新整理的功能,一開始想圖省事,在網上直接找一個現成的,可是嘗試了網上多個版本的下拉重新整理之後發現效果都不怎麼理想。有些是因為功能不完整或有Bug,有些是因為使用起來太複雜,十全十美的還真沒找到。因此我也是放棄了在網上找現成程式碼的想法,

Android中ListView重新整理實現

ListView中的下拉重新整理是非常常見的,也是經常使用的,看到有很多同學想要,那我就整理一下,供大家參考。那我就不解釋,直接上程式碼了。 這裡需要自己重寫一下ListView,重寫程式碼如下: package net.loonggg.listview; impor

SwipeToLoadLayout實現Android重新整理及上載入

最近一段時間需要對手上的專案進行重構,一方面等甲方對業務流程的需求,另一方面由於新配了電腦可以流暢的執行Android Studio了正好也閒著沒事就打算把UI重新搞一搞順便降低各個模組的耦合度,在實現列表的地方噁心到我了。 因為之前一直用的的PullToRefresh在列

Android智慧重新整理框架—SmartRefreshLayout的使用

上個月因為自己太懶了,加上又發生了一點小事,就沒能及時更新部落格,下了班回家面壁思過去吧。 今天這篇文章主要是介紹一下SmartRefreshLayout這個第三方下拉重新整理庫的使用,之前在專案中一直用的都是PullToRefreshLayout這個庫,感覺有不少坑,後

兩款 非常不錯的Android 重新整理,上載入的框架

https://github.com/chrisbanes/Android-PullToRefresh https://github.com/liaohuqiu/android-Ultra-Pull-To-Refresh

打造android萬能上重新整理框架——XRefreshView (一)

一、寫在開頭的話 之所以寫這個東西是因為專案中有用到,需要給stickylistheaders加個重新整理,其實就是個framelayout裡面有個listview的自定義view佈局,但是一些知名的重新整理框架我試了下都不支援,pulltoRefresh和XListVie

Android智慧重新整理框架-SmartRefreshLayout

框架?下拉重新整理控制元件還能框架化?智慧又怎麼回事?二話不多少先上Demo效果圖,咱們再來探個究竟。 Github 傳送門 注意:本文僅僅是部落格文章,主要用於專案介紹和宣傳,由於釋出時間關係,部分內容已經過期,詳細使用文件請跳轉 github

一個強大的重新整理框架android-Ultra-Pull-To-Refresh

最近在學習github上的一個開源專案:android-Ultra-Pull-To-Refresh(下面簡稱UltraPtr) 。這個專案主要用於Android APP中下拉重新整理的功能。 OK,之所以說UltraPtr非常強大,是因為它有以下兩個特點:  1. c

android重新整理,上載入更多

public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerview; private ArrayList<Integer> mList = new ArrayL

打造通用的Android重新整理元件 適用於ListView GridView等各類View

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Android 重新整理

匯入PullToRefresh 1.1 修改library的build.gradle中的sdk版本 //修改前 compileSdkVersion 16 buildToolsVersion “27.0.3”   defaultConfig {  

Android重新整理PtrFrameLayout的使用

Android下拉重新整理PtrFrameLayout的使用 1.介紹: 可以包含所有的控制元件 :ListView, GridView, ScrollView, FrameLayout, 甚至 TextView. 可以自定義重新整理頭(這點非常實用) 使用簡單方

Android 重新整理載入PullToRefresh

PullToRefresh 開發者可以使用 PullToRefresh 對各種控制元件實現下拉重新整理或者上拉載入以及可以自定義重新整理和載入部分的檢視。 目前支援:ScrollView,ListView,WebView,RecyclerView。 PullToRefresh的使用步驟

ListView重新整理具體實現

1、現在gitHub中有ListView的下拉重新整理的框架,不過個人手賤,還是自己做了一個,懂了很多東西,哎,又不是資料結構,只是一些基本的下拉東西,在此留給自己回憶的。 2、不適宜新人學習,因為我基本不載入圖片在這,只留給有基礎的人忘記重新整理的一些重要東西檢視。 主佈局檔案:如果不

Android 重新整理用法

匯入PullToRefresh 1.1 修改library的build.gradle中的sdk版本 //修改前 compileSdkVersion 16 buildToolsVersion “27.0.3” defaultConfig { minSdk

Android重新整理和上載入

先看看XML佈局檔案,下拉重新整理和上拉載入哪個在外層並沒有什麼影響。最裡面嵌套了一個RecycleView。 <android.support.v4.widget.SwipeRefreshLayout     android:id="@+id/gridswipre

iscroll.js 移動端上載入,重新整理功能實現

如下圖所示,我需要做一個上拉載入,下拉重新整理的功能:              首先在 html 中引用這個外掛: <script src="/js/common/iscroll.js"></script> 然後插入我們的資料: <d