转载请标明出处:
http://blog.csdn.net/xuehuayous/article/details/51158759;
本文出自:【Kevin.zhou的博客】
public class UltimateRecyclerView extends PullToRefreshBase {
public UltimateRecyclerView(Context context) {
super(context);
}
public UltimateRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public UltimateRecyclerView(Context context, Mode mode) {
super(context, mode);
}
public UltimateRecyclerView(Context context, Mode mode, AnimationStyle animStyle) {
super(context, mode, animStyle);
}
@Override
public Orientation getPullToRefreshScrollDirection() {
return null;
}
@Override
protected WrapRecyclerView createRefreshableView(Context context, AttributeSet attrs) {
return null;
}
@Override
protected boolean isReadyForPullEnd() {
return false;
}
@Override
protected boolean isReadyForPullStart() {
return false;
}
}
@Override
public final Orientation getPullToRefreshScrollDirection() {
return Orientation.VERTICAL;
}
@Override
protected WrapRecyclerView createRefreshableView(Context context, AttributeSet attrs) {
WrapRecyclerView recyclerView = new InternalWrapRecyclerView(context, attrs);
recyclerView.setId(R.id.ultimate_recycler_view);
return recyclerView;
}
这里为什么使用了一个InternalWrapRecyclerView,这个后面再讲。
@Override
protected boolean isReadyForPullStart() {
return isFirstItemVisible();
}
@Override
protected boolean isReadyForPullEnd() {
return isLastItemVisible();
}
private void init(Context context, AttributeSet attrs) {
// Styleables from XML
TypedArray ua = context.obtainStyledAttributes(attrs, R.styleable.UltimateRecyclerView);
mURecyclerViewExtrasEnabled = ua.getBoolean(R.styleable.UltimateRecyclerView_ptrURecyclerViewExtrasEnabled, true);
ua.recycle();
// Styleables from XML
TypedArray pa = context.obtainStyledAttributes(attrs, com.handmark.pulltorefresh.library.R.styleable.PullToRefresh);
if (mURecyclerViewExtrasEnabled) {
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);
final ViewGroup.LayoutParams hlp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
// Create Loading Views ready for use later
mSvHeaderLoadingFrame = new FrameLayout(getContext());
mHeaderLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_START, pa);
mHeaderLoadingView.setVisibility(View.GONE);
mSvHeaderLoadingFrame.addView(mHeaderLoadingView, lp);
mSvHeaderLoadingFrame.setLayoutParams(hlp);
mRefreshableView.addHeaderView(mSvHeaderLoadingFrame);
mSvFooterLoadingFrame = new FrameLayout(getContext());
mFooterLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_END, pa);
mFooterLoadingView.setVisibility(View.GONE);
mSvFooterLoadingFrame.addView(mFooterLoadingView, lp);
mSvFooterLoadingFrame.setLayoutParams(hlp);
mSvSecondFooterLoadingFrame = new FrameLayout(getContext());
mSvSecondFooterLoadingFrame.setLayoutParams(hlp);
pa.recycle();
}
}
protected class InternalWrapRecyclerView extends WrapRecyclerView {
private boolean mAddedSvFooter = false;
public InternalWrapRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setAdapter(Adapter adapter) {
// Add the Footer View at the last possible moment
if (null != mSvFooterLoadingFrame && !mAddedSvFooter) {
addFooterView(mSvFooterLoadingFrame);
mAddedSvFooter = true;
}
super.setAdapter(adapter);
}
}
@Override
protected void onRefreshing(final boolean doScroll) {
WrapAdapter adapter = mRefreshableView.getAdapter();
if (!mURecyclerViewExtrasEnabled || !getShowViewWhileRefreshing() || null == adapter || adapter.getItemCount() == 0) {
super.onRefreshing(doScroll);
return;
}
super.onRefreshing(false);
final LoadingLayoutBase origLoadingView, recyclerViewLoadingView, oppositeRecyclerViewLoadingView;
final int scrollToPosition, scrollToY;
switch (getCurrentMode()) {
case MANUAL_REFRESH_ONLY:
case PULL_FROM_END:
origLoadingView = getFooterLayout();
recyclerViewLoadingView = mFooterLoadingView;
oppositeRecyclerViewLoadingView = mHeaderLoadingView;
scrollToPosition = mRefreshableView.getBottom();
scrollToY = getScrollY() - getFooterSize();
break;
case PULL_FROM_START:
default:
origLoadingView = getHeaderLayout();
recyclerViewLoadingView = mHeaderLoadingView;
oppositeRecyclerViewLoadingView = mFooterLoadingView;
scrollToPosition = mRefreshableView.getTop();
scrollToY = getScrollY() + getHeaderSize();
break;
}
// 隐藏原来的加载View
origLoadingView.reset();
origLoadingView.hideAllViews();
// 刷新时隐藏尾部,加载时隐藏头部
oppositeRecyclerViewLoadingView.setVisibility(View.GONE);
// 设置RecyclerView内的加载View显示并设置它为刷新状态
recyclerViewLoadingView.setVisibility(View.VISIBLE);
recyclerViewLoadingView.refreshing();
if (doScroll) {
// We need to disable the automatic visibility changes for now
disableLoadingLayoutVisibilityChanges();
// 刷新布局由过度滑动状态恢复
setHeaderScroll(scrollToY);
// 让添加到RecyclerView的刷新头部或者加载尾部显示出来
mRefreshableView.smoothScrollToPosition(scrollToPosition);
// 把整体滚回初始位置
smoothScrollTo(0);
}
}
@Override
protected void onReset() {
if (!mURecyclerViewExtrasEnabled) {
super.onReset();
return;
}
final LoadingLayoutBase originalLoadingLayout, recyclerViewLoadingLayout;
final int scrollToHeight, selection;
final boolean scrollSvToEdge;
WrapAdapter adapter = mRefreshableView.getAdapter();
switch (getCurrentMode()) {
case MANUAL_REFRESH_ONLY:
case PULL_FROM_END:
originalLoadingLayout = getFooterLayout();
recyclerViewLoadingLayout = mFooterLoadingView;
selection = adapter.getItemCount() - 1;
scrollToHeight = getFooterSize();
scrollSvToEdge = Math.abs(getLastVisiblePosition() - selection) <= 1;
break;
case PULL_FROM_START:
default:
originalLoadingLayout = getHeaderLayout();
recyclerViewLoadingLayout = mHeaderLoadingView;
scrollToHeight = -getHeaderSize();
selection = 0;
scrollSvToEdge = Math.abs(getFirstVisiblePosition() - selection) <= 1;
break;
}
// 如果添加到RecyclerView的加载布局在显示
if (recyclerViewLoadingLayout.getVisibility() == View.VISIBLE) {
// 显示原来的加载布局
originalLoadingLayout.showInvisibleViews();
// 隐藏添加到RecyclerView的加载布局
recyclerViewLoadingLayout.setVisibility(View.GONE);
// 滚动隐藏头部或者尾部
if (scrollSvToEdge && getState() != State.MANUAL_REFRESHING) {
mRefreshableView.scrollToPosition(selection);
setHeaderScroll(scrollToHeight);
}
}
super.onReset();
}
public final void setOnLastItemVisibleListener(OnLastItemVisibleListener listener) {
mOnLastItemVisibleListener = listener;
}
public static interface OnLastItemVisibleListener {
public void onLastItemVisible();
}
/**
* 判断最后一个条目是否能够可见
*
* @return boolean:
* @version 1.0
* @date 2016-4-12 14:51:04
* @Author zhou.wenkai
*/
private boolean isLastItemVisible() {
final RecyclerView.Adapter> adapter = getRefreshableView().getAdapter();
// 如果未设置Adapter,都没有添加自然不可见
if(null == adapter) {
return false;
} else {
// 最后一个条目View是否展示
int lastVisiblePosition = getLastVisiblePosition();
// 最后一个显示出来了
if(lastVisiblePosition == mRefreshableView.getAdapter().getItemCount() - 2) {
// 说明最后一个刚刚显示出来
// 这里不希望和PullToRefreshListView中一样只要最后一个显示,每动一下就促发一次回调
if(lastVisiblePosition == mTmplastVisiblePosition + 1) {
mTmplastVisiblePosition = lastVisiblePosition;
return true;
}
}
mTmplastVisiblePosition = lastVisiblePosition;
}
return false;
}
private int getLastVisiblePosition() {
View lastVisibleChild = mRefreshableView.getChildAt(mRefreshableView
.getChildCount() - 1);
return lastVisibleChild != null ? mRefreshableView
.getChildAdapterPosition(lastVisibleChild) : -1;
}
@Override
public void onScrolled(int dx, int dy) {
super.onScrolled(dx, dy);
boolean lastItemVisible = isLastItemVisible();
if(lastItemVisible) {
mOnLastItemVisibleListener.onLastItemVisible();
}
}
@Override
public void setHeaderLayout(LoadingLayoutBase headerLayout) {
super.setHeaderLayout(headerLayout);
try {
Constructor c = headerLayout.getClass().getDeclaredConstructor(new Class[]{Context.class});
LoadingLayoutBase mHeaderLayout = (LoadingLayoutBase)c.newInstance(new Object[]{getContext()});
if(null != mHeaderLayout) {
mSvHeaderLoadingFrame.removeAllViews();
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);
mHeaderLoadingView = mHeaderLayout;
mHeaderLoadingView.setVisibility(View.GONE);
mSvHeaderLoadingFrame.addView(mHeaderLoadingView, lp);
mRefreshableView.getAdapter().notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void setFooterLayout(LoadingLayoutBase footerLayout) {
super.setFooterLayout(footerLayout);
try {
Constructor c = footerLayout.getClass().getDeclaredConstructor(new Class[]{Context.class});
LoadingLayoutBase mFooterLayout = (LoadingLayoutBase)c.newInstance(new Object[]{getContext()});
if(null != mFooterLayout) {
mSvFooterLoadingFrame.removeAllViews();
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);
mFooterLoadingView = mFooterLayout;
mFooterLoadingView.setVisibility(View.GONE);
mSvFooterLoadingFrame.addView(mFooterLoadingView, lp);
mRefreshableView.getAdapter().notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void setAdapter(Adapter adapter) {
// Add the Footer View at the last possible moment
if (null != mSvFooterLoadingFrame && !mAddedSvFooter) {
addFooterView(mSvSecondFooterLoadingFrame);
addFooterView(mSvFooterLoadingFrame);
mAddedSvFooter = true;
}
super.setAdapter(adapter);
}
@Override
public void setSecondFooterLayout(View secondFooterLayout) {
final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);
mSvSecondFooterLoadingFrame.addView(secondFooterLayout, lp);
}
mUltimateRecyclerView = (UltimateRecyclerView) this.findViewById(R.id.main_act_urv);
// 设置头部刷新样式为自定义
mUltimateRecyclerView.setHeaderLayout(new TmallHeaderLayout(this));
WrapRecyclerView mWrapRecyclerView = mUltimateRecyclerView.getRefreshableView();
LayoutInflater inflater = LayoutInflater.from(this);
FrameLayout layout = (FrameLayout) inflater.inflate(R.layout.recycler_header, null);
mAdLoopView = (AdLoopView) layout.findViewById(R.id.main_act_alv);
mWrapRecyclerView.addHeaderView(layout);
// 设置刷新监听
mUltimateRecyclerView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener() {
@Override
public void onRefresh(PullToRefreshBase refreshView) {
new GetDataTask(true).execute();
}
});
// 设置最后一个条目可见监听
mUltimateRecyclerView.setOnLastItemVisibleListener(new PullToRefreshBase.OnLastItemVisibleListener() {
@Override
public void onLastItemVisible() {
boolean hasMoreData = secondFooterLayout.isHasMoreData();
Log.i("", "是否还有更多数据 " + hasMoreData);
if(hasMoreData) {
new GetDataTask(false).execute();
}
}
});
如果您的项目使用 Gradle 构建, 只需要在您的build.gradle
文件添加下面一行到 dependencies
:
compile 'com.kevin:ultimaterecyclerview:1.0.2'