RecyclerView的上拉加载和下拉刷新

来源:互联网 发布:卡拉扬去世 知乎 编辑:程序博客网 时间:2024/06/05 18:48

recyclerview比较麻烦的是上拉加载更多功能,下拉刷新使用的是Google官方的SwipeRefreshLayout控件,实现起来非常简单。

一.上拉加载更多功能实际上就是给RecyclerView增加一个FooterView,然后通过判断是否滑动到了最后一条Item,来控制FooterView的显示和隐藏,接下来我们来看下如何实现:

public class LoadMoreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {    private List<String> dataList;    // 普通布局    private final int TYPE_ITEM = 1;    // 脚布局    private final int TYPE_FOOTER = 2;    // 当前加载状态,默认为加载完成    private int loadState = 2;    // 正在加载    public final int LOADING = 1;    // 加载完成    public final int LOADING_COMPLETE = 2;    // 加载到底    public final int LOADING_END = 3;    public LoadMoreAdapter(List<String> dataList) {        this.dataList = dataList;    }    @Override    public int getItemViewType(int position) {        // 最后一个item设置为FooterView        if (position + 1 == getItemCount()) {            return TYPE_FOOTER;        } else {            return TYPE_ITEM;        }    }    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        // 通过判断显示类型,来创建不同的View        if (viewType == TYPE_ITEM) {            View view = LayoutInflater.from(parent.getContext())                    .inflate(R.layout.adapter_recyclerview, parent, false);            return new RecyclerViewHolder(view);        } else if (viewType == TYPE_FOOTER) {            View view = LayoutInflater.from(parent.getContext())                    .inflate(R.layout.layout_refresh_footer, parent, false);            return new FootViewHolder(view);        }        return null;    }    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        if (holder instanceof RecyclerViewHolder) {            RecyclerViewHolder recyclerViewHolder = (RecyclerViewHolder) holder;            recyclerViewHolder.tvItem.setText(dataList.get(position));        } else if (holder instanceof FootViewHolder) {            FootViewHolder footViewHolder = (FootViewHolder) holder;            switch (loadState) {                case LOADING: // 正在加载                    footViewHolder.pbLoading.setVisibility(View.VISIBLE);                    footViewHolder.tvLoading.setVisibility(View.VISIBLE);                    footViewHolder.llEnd.setVisibility(View.GONE);                    break;                case LOADING_COMPLETE: // 加载完成                    footViewHolder.pbLoading.setVisibility(View.INVISIBLE);                    footViewHolder.tvLoading.setVisibility(View.INVISIBLE);                    footViewHolder.llEnd.setVisibility(View.GONE);                    break;                case LOADING_END: // 加载到底                    footViewHolder.pbLoading.setVisibility(View.GONE);                    footViewHolder.tvLoading.setVisibility(View.GONE);                    footViewHolder.llEnd.setVisibility(View.VISIBLE);                    break;                default:                    break;            }        }    }    @Override    public int getItemCount() {        return dataList.size() + 1;    }    @Override    public void onAttachedToRecyclerView(RecyclerView recyclerView) {        super.onAttachedToRecyclerView(recyclerView);        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();        if (manager instanceof GridLayoutManager) {            final GridLayoutManager gridManager = ((GridLayoutManager) manager);            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {                @Override                public int getSpanSize(int position) {                    // 如果当前是footer的位置,那么该item占据2个单元格,正常情况下占据1个单元格                    return getItemViewType(position) == TYPE_FOOTER ? gridManager.getSpanCount() : 1;                }            });        }    }        /**     * 设置上拉加载状态     *     * @param loadState 0.正在加载 1.加载完成 2.加载到底     */    public void setLoadState(int loadState) {        this.loadState = loadState;        notifyDataSetChanged();    }}

以上代码是自定义了recyclerview的适配器,定义了三种状态,分别是正在加载,加载完成以及滑动到底部,下面来看一下viewholder类的写法

private class RecyclerViewHolder extends RecyclerView.ViewHolder {

TextView tvItem;

RecyclerViewHolder(View itemView) {
super(itemView);
tvItem = (TextView) itemView.findViewById(R.id.tv_item);
}
}

private class FootViewHolder extends RecyclerView.ViewHolder {

ProgressBar pbLoading;
TextView tvLoading;
LinearLayout llEnd;

FootViewHolder(View itemView) {
super(itemView);
pbLoading = (ProgressBar) itemView.findViewById(R.id.pb_loading);
tvLoading = (TextView) itemView.findViewById(R.id.tv_loading);
llEnd = (LinearLayout) itemView.findViewById(R.id.ll_end);
}
}
}

首先定义了布局和数据加载状态的一些标志,然后在getItemViewType方法中设置最后一个Item为FooterView,在onCreateViewHolder方法中根据viewType来加载不同的布局,最后在onBindViewHolder方法中设置一下加载的状态显示就OK了,由于多了一个FooterView,所以要记得在getItemCount方法的返回值中加上1。

二. 到这里一个线性布局列表的Adapter就完成了,但是我们的recyclerview在实际的使用中还经常使用到网格布局,针对网格布局,我们要再增加一些处理

@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) {    super.onAttachedToRecyclerView(recyclerView);    RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();    if (manager instanceof GridLayoutManager) {        final GridLayoutManager gridManager = ((GridLayoutManager) manager);        gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {            @Override            public int getSpanSize(int position) {                // 如果当前是footer的位置,那么该item占据2个单元格,正常情况下占据1个单元格                return getItemViewType(position) == TYPE_FOOTER ? gridManager.getSpanCount() : 1;            }        });    }}

 

在Adapter中重写onAttachedToRecyclerView方法,首先判断当前是否为网格布局,然后给GridLayoutManager设置一个SpanSizeLookup,这是一个抽象类,里面有一个抽象方法getSpanSize,这个方法的返回值决定了每个Item占据的单元格数。

如果我们实现的是一个两列的网格布局,那么当前Item是FooterView的话需要占据两个单元格才能横向充满屏幕,所以需要返回2(GridLayoutManager的getSpanCount方法获取到的是当前一行中单元格的数量),正常情况下每个Item占据一个单元格。

阅读全文
0 0