1. 關於下拉刷新
2. 實現原理
以上三部分總結的說來,就是如下圖所示的這種佈局結構:
3. 具體實現
1、IPullToRefresh<T extends View>
- 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);
- }
2、PullToRefreshBase<T extends View>
- 處理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會根據狀態去顯示相應的界面式樣。
- 對於ListView,ScrollView,WebView這三種情況,他們是否滑動到最頂部或是最底部的實現是不一樣的,所以,在PullToRefreshBase類中需要調用兩個抽象方法來判斷當前的位置是否在頂部或底部,而其派生類必須要實現這兩個方法。比如對於ListView,它滑動到最頂部的條件就是第一個child完全可見並且first postion是0。這兩個抽象方法是:
- /**
- * 判斷刷新的View是否滑動到頂部
- *
- * @return true表示已經滑動到頂部,否則false
- */
- protected abstract boolean isReadyForPullDown();
- /**
- * 判斷刷新的View是否滑動到底
- *
- * @return true表示已經滑動到底部,否則false
- */
- protected abstract boolean isReadyForPullUp();
- 創建可下拉刷新的View(也就是content view)的抽象方法是
- /**
- * 創建可以刷新的View
- *
- * @param context context
- * @param attrs 屬性
- * @return View
- */
- protected abstract T createRefreshableView(Context context, AttributeSet attrs);
- getContentSize
這個方法返回當前這個刷新Layout的大小,通常返回的是佈局的高度,爲了以後可以擴展爲水平拉動,所以方法名字沒有取成getLayoutHeight()之類的,這個返回值,將會作爲鬆手後是否可以刷新的臨界值,如果下拉的偏移值大於這個值,就認爲可以刷新,否則不刷新,這個方法必須由派生類來實現。
- setState
4. 如何使用
- @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);
- }