1. 程式人生 > >讓Android Support V4中的SwipeRefreshLayout支援上拉載入更多

讓Android Support V4中的SwipeRefreshLayout支援上拉載入更多

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

前言

 原來的Android SDK中並沒有下拉重新整理元件,但是這個元件確實絕大多數APP必備的一個部件。好在google在v4包中出了一個SwipeRefreshLayout,但是這個元件只支援下拉重新整理,不支援上拉載入更多的操作。因此,我們就來簡單的擴充套件一下這個元件以實現上拉下載的目的。

基本原理

 上拉載入或者說滾動到底部時自動載入,都是通過判斷是否滾動到了ListView或者其他View的底部,然後觸發相應的操作,這裡我們以ListView來說明。因此我們需要在監聽ListView的滾動事件,當ListView滾動到底部時自動觸發載入操作;但是當用戶支援手指滑動螢幕,沒有滾動時,我們也需要讓它載入,因此這種情形就是上拉載入更多。所以我們需要在觸控事件裡面進行判斷,如果到了底部,且使用者是上拉操作,那麼執行載入更多。更多關於下拉重新整理、上拉載入請參考打造通用的Android下拉重新整理元件(適用於ListView、GridView等各類View)
 時間有限,直接上程式碼吧。

實現程式碼

/** * 繼承自SwipeRefreshLayout,從而實現滑動到底部時上拉載入更多的功能. *  * @author mrsimple */public class RefreshLayout extends SwipeRefreshLayout implements OnScrollListener {    /**     * 滑動到最下面時的上拉操作     */
    private int mTouchSlop;    /**     * listview例項     */    private ListView mListView;    /**     * 上拉監聽器, 到了最底部的上拉載入操作     */    private OnLoadListener mOnLoadListener;    /**     * ListView的載入中footer     */    private View mListViewFooter;    /**     * 按下時的y座標     */    private int mYDown;    /**     * 擡起時的y座標, 與mYDown一起用於滑動到底部時判斷是上拉還是下拉     */    private int mLastY;    /**     * 是否在載入中 ( 上拉載入更多 )     */    private boolean isLoading = false;    /**     * @param context     */    public RefreshLayout(Context context) {        this(context, null);    }    public RefreshLayout(Context context, AttributeSet attrs) {        super(context, attrs);        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();        mListViewFooter = LayoutInflater.from(context).inflate(R.layout.listview_footer, null,                false);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        // 初始化ListView物件        if (mListView == null) {            getListView();        }    }    /**     * 獲取ListView物件     */    private void getListView() {        int childs = getChildCount();        if (childs > 0) {            View childView = getChildAt(0);            if (childView instanceof ListView) {                mListView = (ListView) childView;                // 設定滾動監聽器給ListView, 使得滾動的情況下也可以自動載入                mListView.setOnScrollListener(this);                Log.d(VIEW_LOG_TAG, "### 找到listview");            }        }    }    /*     * (non-Javadoc)     * @see android.view.ViewGroup#dispatchTouchEvent(android.view.MotionEvent)     */    @Override    public boolean dispatchTouchEvent(MotionEvent event) {        final int action = event.getAction();        switch (action) {            case MotionEvent.ACTION_DOWN:                // 按下                mYDown = (int) event.getRawY();                break;            case MotionEvent.ACTION_MOVE:                // 移動                mLastY = (int) event.getRawY();                break;            case MotionEvent.ACTION_UP:                // 擡起                if (canLoad()) {                    loadData();                }                break;            default:                break;        }        return super.dispatchTouchEvent(event);    }    /**     * 是否可以載入更多, 條件是到了最底部, listview不在載入中, 且為上拉操作.     *      * @return     */    private boolean canLoad() {        return isBottom() && !isLoading && isPullUp();    }    /**     * 判斷是否到了最底部     */    private boolean isBottom() {        if (mListView != null && mListView.getAdapter() != null) {            return mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() - 1);        }        return false;    }    /**     * 是否是上拉操作     *      * @return     */    private boolean isPullUp() {        return (mYDown - mLastY) >= mTouchSlop;    }    /**     * 如果到了最底部,而且是上拉操作.那麼執行onLoad方法     */    private void loadData() {        if (mOnLoadListener != null) {            // 設定狀態            setLoading(true);            //            mOnLoadListener.onLoad();        }    }    /**     * @param loading     */    public void setLoading(boolean loading) {        isLoading = loading;        if (isLoading) {            mListView.addFooterView(mListViewFooter);        } else {            mListView.removeFooterView(mListViewFooter);            mYDown = 0;            mLastY = 0;        }    }    /**     * @param loadListener     */    public void setOnLoadListener(OnLoadListener loadListener) {        mOnLoadListener = loadListener;    }    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {    }    @Override    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,            int totalItemCount) {        // 滾動時到了最底部也可以載入更多        if (canLoad()) {            loadData();        }    }    /**     * 載入更多的監聽器     *      * @author mrsimple     */    public static interface OnLoadListener {        public void onLoad();    }}

 listview_footer.xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:background="@color/umeng_comm_comments_bg"    android:gravity="center"    android:paddingBottom="8dip"    android:paddingTop="5dip" >    <ProgressBar        android:id="@+id/pull_to_refresh_load_progress"        style="@android:style/Widget.ProgressBar.Small.Inverse"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerVertical="true"        android:layout_centerHorizontal="true"        android:paddingRight="100dp"        android:indeterminate="true" />    <TextView        android:id="@+id/pull_to_refresh_loadmore_text"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:gravity="center"        android:paddingTop="5dip"        android:text="@string/load"        android:textAppearance="?android:attr/textAppearanceMedium"        android:textColor="@android:color/darker_gray"        android:textSize="14sp"        android:textStyle="bold" /></RelativeLayout>

使用示例

 refresh.xml佈局檔案:
<?xml version="1.0" encoding="utf-8"?><myview.RefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/swipe_layout"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <ListView        android:id="@+id/listview"        android:layout_width="match_parent"        android:layout_height="match_parent" >    </ListView></myview.RefreshLayout>

 activity中的使用 : 
/** * @author mrsimple */public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);          setContentView(R.layout.refresh);        // 模擬一些資料        final List<String> datas = new ArrayList<String>();        for (int i = 0; i < 20; i++) {            datas.add("item - " + i);        }        // 構造介面卡        final BaseAdapter adapter = new ArrayAdapter<String>(this,                android.R.layout.simple_list_item_1,                datas);        // 獲取listview例項        ListView listView = (ListView) findViewById(R.id.listview);        listView.setAdapter(adapter);        // 獲取RefreshLayout例項        final RefreshLayout myRefreshListView = (RefreshLayout)                findViewById(R.id.swipe_layout);        // 設定下拉重新整理時的顏色值,顏色值需要定義在xml中        myRefreshListView                .setColorScheme(R.color.umeng_comm_text_topic_light_color,                        R.color.umeng_comm_yellow, R.color.umeng_comm_green,                        R.color.umeng_comm_linked_text);        // 設定下拉重新整理監聽器        myRefreshListView.setOnRefreshListener(new OnRefreshListener() {            @Override            public void onRefresh() {                Toast.makeText(MainActivity.this, "refresh", Toast.LENGTH_SHORT).show();                myRefreshListView.postDelayed(new Runnable() {                    @Override                    public void run() {                        // 更新資料                        datas.add(new Date().toGMTString());                        adapter.notifyDataSetChanged();                        // 更新完後呼叫該方法結束重新整理                        myRefreshListView.setRefreshing(false);                    }                }, 1000);            }        });        // 載入監聽器        myRefreshListView.setOnLoadListener(new OnLoadListener() {            @Override            public void onLoad() {                Toast.makeText(MainActivity.this, "load", Toast.LENGTH_SHORT).show();                myRefreshListView.postDelayed(new Runnable() {                    @Override                    public void run() {                        datas.add(new Date().toGMTString());                        adapter.notifyDataSetChanged();                        // 載入完後呼叫該方法                        myRefreshListView.setLoading(false);                    }                }, 1500);            }        });    }    }

效果圖

 



 github連結 : 下拉重新整理庫  示例在android_my_pull_demo工程中,進入demo後點擊最後一個按鈕檢視效果即可。注意,在重新整理和載入時,需要有一定的延時才能看到效果,這裡我們用postDelay來模擬網路請求等延時操作,否則將看不到載入效果。這裡只提供一個實現思路,程式碼不太完善,需要用的請自行完善並測試。  
 注意  如果出現 HeaderViewListAdapter 轉換異常,那麼請使用 RefreshLvLayout中的setAdapter 函式為ListView設定Adapter, 這樣可以確保在設定Adapter之前已經添加了Footer。
           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述