您的位置:首页 > 移动开发 > Android开发

RecyclerView 轻松实现下拉刷新,上拉加载更多,添加HeaderView

2017-03-08 18:49 543 查看

一,下拉加载更多

用SwipeRefreshLayout 包裹RecyclerView

如下布局文件代码所示:

<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recylerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>


Java代码如下所示:

mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refresh_layout);
mRefreshLayout.setColorSchemeColors(Color.BLUE, Color.GREEN, Color.RED, Color.YELLOW);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
Log.d(TAG, "refreshing-------------->");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
mList.add(0, "新的");
mMyAdapter.notifyDataSetChanged();
mRefreshLayout.setRefreshing(false);
}
}, 2000);
}
});


为RecyclerView添加下拉刷新监听mRefreshLayout.setOnRefreshListener(mOnRefreshListener);

利用以上代码便可简单实现下拉刷新。

二、上拉加载更多,添加HeaderView

上拉加载更多、添加HeaderView稍微复杂些,按照下面几个步骤便可实现。

HeaderView:显示头部View

NormalView:显示正常条目的View

FooterView:显示加载更多的View

1、重写RecyclerView.Adapter的getItemCount()方法

因为添加了HeaderView和FooterView,在重写getItemCount()方法的时候要注意加上HeaderView和FooterView2个View的个数,在编程的时候可以根据是否添加了HeaderView和FooterView来动态的设置个数,如:

@Override
public int getItemCount() {
return list == null ? totalAddationalItems() : list.size() + totalAddationalItems();
}

private int totalAddationalItems() {
int offset = 0;
if (mIsLoadmore) offset++;
if (mIsHeader) offset++;
Log.d(TAG,"offset:"+offset);
return offset;
}


2、重写RecyclerView.Adapter的getItemViewType()

利用getItemViewType返回的类型判断是加载HeaderView、NormalView还是FooterView.如:

private static final int HEADER_TYPE = 0;
private static final int NORMAL_TYPE = 1;
private static final int FOOTER_TYPE = 2;
@Override
public int getItemViewType(int position) {
int last_item = getItemCount() - 1;//最后一个
Log.d(TAG,"getItemViewType position:"+(position-1)+" last_item:"+last_item);
if (position == 0 && mIsHeader) {
return HEADER_TYPE;
} else if (position == last_item && mIsLoadmore) {
return FOOTER_TYPE;
}else {
return NORMAL_TYPE;
}
}


3、重写RecyclerView.Adapter的onCreateViewHolder() 方法

重写该方法,实现根据不同的类型加载不同的View

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == NORMAL_TYPE) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_item, parent, false);
return new MyViewHolder(view);
} else if (viewType == FOOTER_TYPE) {
mFooterView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.footer_layout, parent, false);
mFooterHolder = new MyFooterHolder(mFooterView);
return mFooterHolder;
} else if (viewType == HEADER_TYPE) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.header_view_layout, parent, false);
return new MyHeaderView(view);
} else {
return null;
}
}


4、重新RecyclerView.Adapter的onBindViewHolder()方法

重写该方法的时候要注意position和数据源List的索引的区别,需要将position-1才和List的索引对称。

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (NORMAL_TYPE == getItemViewType(position)) {
if (list != null && list.size() > position - 1 && position - 1 >= 0) {
Log.d(TAG, "onBindViewHolder position:" + (position - 1));
MyViewHolder myViewHolder = (MyViewHolder) holder;
myViewHolder.tv.setText(list.get(position - 1));
}
}
}


5、处理FooterView 显示加载更多的View

这一步是处理FooterView的显示和隐藏,当还有数据要加载的时候显示FooterView并请求数据,

FooterViewHolder:

public static class MyFooterHolder extends RecyclerView.ViewHolder {
private View mLoadingView;
private View mEndView;

public MyFooterHolder(View itemView) {
super(itemView);
mLoadingView = itemView.findViewById(R.id.loading_vs);
mEndView = itemView.findViewById(R.id.end_viewstub);
}

public void setData(ITEM_STATUS status) {
switch (status) {
case NORMAL:
setAllGone();
break;
case LOADING:
setAllGone();
mLoadingView.setVisibility(View.VISIBLE);
Log.d("ad", "ddddd");
break;
case END:
setAllGone();
break;
}
}
private void setAllGone() {
mLoadingView.setVisibility(View.GONE);
mEndView.setVisibility(View.GONE);
}
}


6、实现RecyclerView.OnScrollListener

这一步非常重要,用于判断RecyclerView是否滑动到底部。主要是找到mLastVisibleItemPosition的值,根据不同的layoutManager做不同的处理,为RecyclerView添加滚动监听mRecyclerView.addOnScrollListener(mOnScrollListener);

public void setFooterStatus(MyAdapter.ITEM_STATUS footerStatus) {
this.mFooterStatus = footerStatus;
changeFooterViewState();
}

private void changeFooterViewState(){
if (mMyAdapter != null && mMyAdapter.getFooterHolder() != null){
Log.d(TAG, "changeFooterViewState-------------->");
mMyAdapter.getFooterHolder().setData(this.mFooterStatus);
}
}

SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
Log.d(TAG, "refreshing-------------->");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
mList.add(0, "新的");
mMyAdapter.notifyDataSetChanged();
mRefreshLayout.setRefreshing(false);
}
}, 2000);
}
};

private abstract class CustomOnScrollListener extends RecyclerView.OnScrollListener {
private LayoutManagerType mLayoutManagerType;
private int mLastVisibleItemPosition;
private int[] mLastVisibleItemPositionStaggered;
private int mCurrentScrollState;

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (mLayoutManagerType == null) {
if (layoutManager instanceof GridLayoutManager) {
mLayoutManagerType = LayoutManagerType.GRID;
} else if (layoutManager instanceof LinearLayoutManager) {
mLayoutManagerType = LayoutManagerType.LINEAR;
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
mLayoutManagerType = LayoutManagerType.STAGGERED_GRID;
} else {
throw new RuntimeException("not support");
}
}
switch (mLayoutManagerType) {
case LINEAR:
mLastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
break;
case GRID:
mLastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
break;
case STAGGERED_GRID:
StaggeredGridLayoutManager sg = (StaggeredGridLayoutManager) layoutManager;
if (mLastVisibleItemPositionStaggered == null) {
mLastVisibleItemPositionStaggered = new int[sg.getSpanCount()];
}
sg.findLastVisibleItemPositions(mLastVisibleItemPositionStaggered);
mLastVisibleItemPosition = findMax(mLastVisibleItemPositionStaggered);
break;
}
}

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
mCurrentScrollState = newState;
int visiableItemCount = recyclerView.getLayoutManager().getChildCount();
int totalItemCount = recyclerView.getLayoutManager().getItemCount();
if (visiableItemCount > 0 && mCurrentScrollState == RecyclerView.SCROLL_STATE_IDLE
&& mLastVisibleItemPosition >= totalItemCount - 1) {
onLoadMore(recyclerView);
}
}

public abstract void onLoadMore(RecyclerView recyclerView);
}

private enum LayoutManagerType {
LINEAR,
GRID,
STAGGERED_GRID,
}

private RecyclerView.OnScrollListener mOnScrollListener = new CustomOnScrollListener() {
@Override
public void onLoadMore(RecyclerView recyclerView) {
if (mFooterStatus == MyAdapter.ITEM_STATUS.LOADING){
return;
}
Log.d(TAG, "onLoadMore----->");
if (mList.size() < 30){
requestData();
}else {
mMyAdapter.enableLoadmore(false);
//mMyAdapter.enableHeader(false);
setFooterStatus(MyAdapter.ITEM_STATUS.END);
mMyAdapter.notifyDataSetChanged();
}
}
};

private void requestData() {
setFooterStatus(MyAdapter.ITEM_STATUS.LOADING);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
int start = mMyAdapter.getItemCount()-1;
mList.add("str"+(mList.size()+1));
mList.add("str"+(mList.size()+1));
mList.add("str"+(mList.size()+1));
if (mList.size() >= 30){
mMyAdapter.enableLoadmore(false);
//mMyAdapter.enableHeader(false);
setFooterStatus(MyAdapter.ITEM_STATUS.END);
}else {
setFooterStatus(MyAdapter.ITEM_STATUS.NORMAL);
}
mMyAdapter.notifyDataSetChanged();
}
}, 1500);
}

private int findMax(int[] lastPositions) {
int max = Integer.MIN_VALUE;
for (int value : lastPositions) {
Log.d(TAG, "value:" + value + " max:" + max);
if (value > max)
max = value;
}
return max;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android
相关文章推荐