SwipeRefreshLoadLayout + RecyclerView 實現下列刷新,上拉加載

使用過 SwipeRefreshLayout 的都知道,這個控件谷歌只添加下拉刷新,如果需要上拉加載,就需要自己去實現,這裏是結合RecyclerView添加了上拉加載功能,列出代碼僅供參考。

這裏是SwipeRefreshLoadLayout源碼:

/**
 * @author ttarfall
 * @date 2016-03-25 12:32
 */
public class SwipeRefreshLoadLayout extends SwipeRefreshLayout {
    private static final String TAG = "SwipeRefreshLoadLayout";

    /**
     * 滑動到最下面時的上拉操作 有效距離
     */
    private int mTouchSlop;
    private RecyclerView recyclerView;
    /**
     * 刷新回調接口
     */
    private OnRefreshListener mListener;
    /**
     * 上拉加載回調接口
     */
    private OnLoadListener onLoadListener;
    private float downY, lastY;
    /**
     * 是否在加載中 ( 上拉加載更多 )
     */
    private boolean isLoading = false;
    /**
     * 設置是否支持自動加載 默認不支持
     */
    private boolean mIsAutoLoad = false;
    /**
     * 支持自動上拉加載觸發的有效行數
     */
    private int autoLoadCount = 1;
    /**
     * 自動刷新線程
     */
    private Runnable autoRefreshRunnable;
    /**
     * 加載數據線程
     */
    private Runnable loadDataRunnable;

    public SwipeRefreshLoadLayout(Context context) {
        this(context, null);
    }

    public SwipeRefreshLoadLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        getView();
        setColorSchemeColors(getResources().getColor(R.color.bg_orange_red));
    }

    /**
     * 設置加載狀態
     *
     * @param isLoading
     */
    public void setIsLoading(boolean isLoading) {
        this.isLoading = isLoading;
    }

    /**
     * 是否正在加載中
     *
     * @return
     */
    public boolean isLoading() {
        return isLoading;
    }

    /**
     * 設置是否自動上拉加載
     *
     * @param isAutoLoad
     */
    public void setAutoLoad(boolean isAutoLoad) {
        mIsAutoLoad = isAutoLoad;
    }

    @Override
    public void setOnRefreshListener(OnRefreshListener listener) {
        super.setOnRefreshListener(listener);
        mListener = listener;
    }

    /**
     * 默認等待時間
     */
    private static final long DEFAULT_DELAYMILLIS = 300;

    /**
     * 自動下拉刷新
     */
    public void setAutoRefreshing() {
        setAutoRefreshing(DEFAULT_DELAYMILLIS);
    }

    /**
     * 啓動自動刷新
     *
     * @param delayMillis
     */

    private void setAutoRefreshing(final long delayMillis) {
        if (autoRefreshRunnable == null && !isRefreshing() && !isLoading) {//啓動自動刷新,前提是界面不處於刷新中和加載中
            autoRefreshRunnable = new Runnable() {
                @Override
                public void run() {
                    int height = getHeight();
                    if (height > 0) {//只有視圖創建以後,高度纔會大於0,因此在視圖創建以後再發起自動刷新
                        if (mListener != null) {
                            setRefreshing(true);
                            mListener.onRefresh();
                        }
                    } else {
                        setAutoRefreshing(delayMillis);
                    }
                }
            };

        }
        handler.postDelayed(autoRefreshRunnable, delayMillis);
    }

    public void setRefreshing(boolean refreshing) {
        if (isLoading) {
            super.setRefreshing(false);
        } else {
            super.setRefreshing(refreshing);
            getView();
            if (recyclerView != null) {
                RecyclerView.Adapter a = recyclerView.getAdapter();
                if (a instanceof BaseLoadAdapter) {
                    ((BaseLoadAdapter) a).setLoading(false);
                }
            }
        }
    }

    private void getView() {
        //當RecyclerView視圖爲空,並且使用了上拉加載監聽回調才獲取視圖
        if (recyclerView == null && onLoadListener != null) {
            getView(this);
        }
    }

    private void getView(View viewParent) {
        if (viewParent instanceof ViewGroup) {
            int count = ((ViewGroup) viewParent).getChildCount();
            for (int i = 0; i < count; i++) {
                View view = ((ViewGroup) viewParent).getChildAt(i);
                if (view instanceof RecyclerView) {
                    recyclerView = (RecyclerView) view;
                    RecyclerView.Adapter a = recyclerView.getAdapter();
                    if (a instanceof BaseLoadAdapter)
                        ((BaseLoadAdapter) a).setSwipeRefreshLoadLayout(this);
                    break;
                } else {
                    getView(view);
                }
            }
        }
    }

    public void setOnLoadListener(OnLoadListener onLoadListener) {
        this.onLoadListener = onLoadListener;
    }

    public OnLoadListener getOnLoadListener() {
        return onLoadListener;
    }

    /**
     * 判斷是否到了最底部
     */
    private boolean isBottom() {
        getView();
        if (recyclerView != null) {
            RecyclerView.Adapter a = recyclerView.getAdapter();
            RecyclerView.LayoutManager m = recyclerView.getLayoutManager();
            if (m instanceof LinearLayoutManager) {
                LinearLayoutManager lm = (LinearLayoutManager) m;
                if (mIsAutoLoad) {
                    return lm.findLastCompletelyVisibleItemPosition() > a.getItemCount() - autoLoadCount;
                } else {
                    return lm.findLastCompletelyVisibleItemPosition() == a.getItemCount() - 1;
                }
            }
        }


        return false;
    }

    /**
     * 設置觸發自動上拉加載的有效行數
     *
     * @param count
     */
    public void setAutoLoadCount(int count) {
        if (count < 1) {
            return;
        }
        if (!mIsAutoLoad) {
            mIsAutoLoad = !mIsAutoLoad;
        }
        autoLoadCount = count;
    }

    public int getAutoLoadCount() {
        return autoLoadCount;
    }

    /**
     * 是否是上拉操作
     *
     * @return
     */
    private boolean isPullUp() {
        return (downY - lastY) >= mTouchSlop;
    }

    /**
     * 是否可以加載更多, 條件是到了最底部, View不在加載中, 且爲上拉操作, 並且不是下拉刷新
     *
     * @return
     */
    private boolean canLoad() {
        return isBottom() && !isLoading && isPullUp() && !isRefreshing();
    }

    private int msgCount = 0;
    private boolean isCountineMove = false;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MotionEvent.ACTION_MOVE:
                    if (msgCount == 1) {
                        if (!isLoading && onLoadListener != null) {//當正在load不在進入執行
                            if (isPullUp()) {
                                getView();
                                if (recyclerView != null) {
                                    RecyclerView.Adapter a = recyclerView.getAdapter();
                                    if (a instanceof BaseLoadAdapter) {
                                        ((BaseLoadAdapter) a).setLoadBefore();
                                    }
                                }
                            }
                        }
                        msgCount = 0;
                    } else {
                        if (msgCount > 0) {
                            msgCount--;
                        } else {
                            msgCount = 0;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (!isCountineMove) {
                        if (!isLoading && onLoadListener != null) {//當正在load不在進入執行
                            if (canLoad()) {
                                msgCount = 0;//如果開始加重下一頁,msgCount爲0
                                loadData();
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
            super.handleMessage(msg);
        }
    };

    private long historyTime = 0;

    /**
     * 是否可以發送消息
     *
     * @return
     */
    private boolean isSendMessage() {
        long curTime = System.currentTimeMillis();
        if (curTime - historyTime > 500) {
            historyTime = curTime;
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!isLoading && onLoadListener != null) {//當正在load不在進入執行
                    downY = ev.getY();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (!isLoading && onLoadListener != null && isSendMessage()) {
                    isCountineMove = true;
                    msgCount++;
                    LogUtil.i("action=" + MotionEvent.ACTION_MOVE + ", msgCount=" + msgCount);
                    lastY = ev.getY();
                    Message msg = new Message();
                    msg.what = MotionEvent.ACTION_MOVE;
                    handler.sendMessageDelayed(msg, 500);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!isLoading && onLoadListener != null) {
                    isCountineMove = false;
                    LogUtil.i("action=" + MotionEvent.ACTION_MOVE + ", msgCount=" + msgCount);
                    lastY = ev.getY();
                    Message msg = new Message();
                    msg.what = MotionEvent.ACTION_UP;
                    handler.sendMessageDelayed(msg, 500);
                }
                break;
            default:
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * @param loading
     */
    public void setLoading(boolean loading) {
        isLoading = loading;
        if (!isLoading) {
            downY = 0;
            lastY = 0;
        }
        getView();
        if (recyclerView != null) {
            RecyclerView.Adapter a = recyclerView.getAdapter();
            if (a instanceof BaseLoadAdapter) {
                ((BaseLoadAdapter) a).setLoading(loading);
            }
        }
    }

    /**
     * 如果到了最底部,而且是上拉操作.那麼執行onLoad方法
     */
    private void loadData() {
        DebugUtil.i(TAG, "loadData 方法執行");
        if (onLoadListener != null) {
            // 設置狀態
            setLoading(true);
            if (loadDataRunnable == null)
                loadDataRunnable = new Runnable() {
                    @Override
                    public void run() {
                        onLoadListener.onLoad();
                    }
                };
            handler.postDelayed(loadDataRunnable, 500);
        } else {
            setLoading(false);
        }
    }

    /**
     * 加載更多的監聽器
     *
     * @author mrsimple
     */
    public interface OnLoadListener {
        public void onLoad();
    }
}
發佈了37 篇原創文章 · 獲贊 26 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章