上一篇博客记录了如何为RecyclerView添加头布局和脚布局,添加这个有什么用呢,当然主要是为了下拉刷新和上拉加载更多了,不然单独的添加两个布局也没有多大意义。
为RecyclerView添加HeaderView和FooterView传送门
上代码:
首先需要先将HeaderView和FooterView设置为不可见(以HeaderView为例,FooterView原理差不多,一会儿贴代码):
public void addHeaderView(View view) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(params);
view.setVisibility(GONE);
FixedViewInfo info = new FixedViewInfo();
info.view = view;
info.viewType = BASE_HEADER_VIEW_TYPE + mHeaderViewInfos.size();
mHeaderViewInfos.clear();
mHeaderViewInfos.add(info);
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
然后添加回调方法:
//定义一些需要用到的变量
private int lastItem;
private int firstItem;
private boolean isLoading = false;
private boolean isRefreshing = false;
private OnRefreshListener onRefreshListener;
private OnLoadMoreListener onLoadMoreListener;
private OnScrollListener mOnScrollListener1, mOnScrollListener2;
public interface OnRefreshListener {
void onRefresh();
}
public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
this.onRefreshListener = onRefreshListener;
if (mOnScrollListener1 == null) {
mOnScrollListener1 = new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//当第一个可见item等于JeaderView的个数,并且是未滑动的状态下才会刷新
if (firstItem == ((WrapperRecyclerViewAdapter) mAdapter).getHeadersCount()
&& newState == RecyclerView.SCROLL_STATE_IDLE
&& !isRefreshing) {
//将HeaderView设为可见
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) getHeaderView(0).getLayoutParams();
params.width = RecyclerView.LayoutParams.MATCH_PARENT;
params.height = RecyclerView.LayoutParams.WRAP_CONTENT;
getHeaderView(0).setLayoutParams(params);
getHeaderView(0).setVisibility(VISIBLE);
isRefreshing = true;
//调用下拉刷新的方法
HeaderRecyclerView.this.onRefreshListener.onRefresh();
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//得到当前第一个可见item
firstItem = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
}
};
this.addOnScrollListener(mOnScrollListener1);
}
}
在数据加载完成后,调用两个方法:
public void setRefreshComplete() {
//重新将HeaderView设为不可见,并刷新适配器
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) getHeaderView(0).getLayoutParams();
params.width = 0;
params.height = 0;
getHeaderView(0).setLayoutParams(params);
getHeaderView(0).setVisibility(GONE);
this.getAdapter().notifyDataSetChanged();
isRefreshing = false;
}
hrvTest.setOnRefreshListener(new HeaderRecyclerView.OnRefreshListener() {
@Override
public void onRefresh() {
//模拟下拉刷新
mHandler.sendEmptyMessageDelayed(1, 3000);
}
});
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
for (int i = 0; i < 5; i++) {
mList.add(0, "onRefresh " + i);
}
//数据加载完成后调用RecyclerView中的方法
hrvTest.setRefreshComplete();
}
if (msg.what == 2) {
for (int i = 0; i < 5; i++) {
mList.add("onLoadMore " + i);
}
hrvTest.setLoadMoreComplete();
}
}
};
上拉加载更多,原理差不多,直接贴代码:
public void addFooterView(View view) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(params);
view.setVisibility(GONE);
FixedViewInfo info = new FixedViewInfo();
info.view = view;
info.viewType = BASE_FOOTER_VIEW_TYPE + mFooterViewInfos.size();
mFooterViewInfos.clear();
mFooterViewInfos.add(info);
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
if (mOnScrollListener2 == null) {
mOnScrollListener2 = new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (lastItem == mAdapter.getItemCount() - ((WrapperRecyclerViewAdapter) mAdapter).getHeadersCount() - ((WrapperRecyclerViewAdapter) mAdapter).getFootersCount()
&& newState == RecyclerView.SCROLL_STATE_IDLE
&& !isLoading) {
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) getFooterView(0).getLayoutParams();
params.width = RecyclerView.LayoutParams.MATCH_PARENT;
params.height = RecyclerView.LayoutParams.WRAP_CONTENT;
getFooterView(0).setLayoutParams(params);
getFooterView(0).setVisibility(VISIBLE);
isLoading = true;
HeaderRecyclerView.this.onLoadMoreListener.onLoadMore();
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
lastItem = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
}
};
this.addOnScrollListener(mOnScrollListener2);
}
}
public void setLoadMoreComplete() {
RecyclerView.LayoutParams params = (LayoutParams) getFooterView(0).getLayoutParams();
params.width = 0;
params.height = 0;
getFooterView(0).setLayoutParams(params);
getFooterView(0).setVisibility(View.GONE);
this.getAdapter().notifyDataSetChanged();
isLoading = false;
}
hrvTest.setOnLoadMoreListener(new HeaderRecyclerView.OnLoadMoreListener() {
@Override
public void onLoadMore() {
//模拟加载更多
mHandler.sendEmptyMessageDelayed(2, 3000);
}
});
不出意外的话,就可以看到下拉和上拉的效果啦。
这是第一次模仿着写一个自定义View,虽然不是自己创造的,不过原理也弄懂了七七八八,也还有点缺陷,就是下拉和上拉没有添加动画,后面会继续优化这个。
在技术的道路上,为自己加油。