使用過 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();
}
}