参考连接1:http://blog.csdn.net/bboyfeiyu/article/details/39935329

 

直奔主题,按照上面参考链接确实是满足需求,但RecyclerView作为一个比ListView更灵活的一个控件,完全取代ListView只是时间的问题。所以这篇博文是记录我自己的实现方法。

首先是RecyclerView增加上拉的时候 加载中的view动画,可以沿用上面参考链接的listview_footer.xml

在ListView中 我们可以用addHeaderView或者addFooterView添加头尾,但RecyclerView并没有这个功能,网上参考是改写RecyclerViewAdapter

 1 public class RecyclerViewAdapter extends RecyclerView.Adapter<ViewHolder> {
 2 
 3     private static final int TYPE_ITEM = 0;
 4     private static final int TYPE_FOOTER = 1;
 5     private Context mContext;
 6     private List<listItemBean> mItemsList;
 7 
 8     public RecyclerViewAdapter(Context context, List<listItemBean> itemsList) {
 9         mContext=context;
10         mItemsList = itemsList;
11     }
12 
13     @Override
14     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
15         if (viewType == TYPE_ITEM) {
16             View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_list_item,parent,false);
17             return new ItemViewHolder(view);
18         } else if (viewType == TYPE_FOOTER) {
19             View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_footer,parent,false);
20             view.setVisibility(View.GONE);
21             return new FooterViewHolder(view);
22         }
23         return null;
24     }
25 
26 
27     @Override
28     public void onBindViewHolder(ViewHolder holder, int position) {
29         if (holder instanceof ItemViewHolder) {
30             listItemBean itemBean = mItemsList.get(position);
31             ((ItemViewHolder)holder).mDetailTextView.setText(itemBean.getDetailText());
32             ((ItemViewHolder)holder).mMainTextView.setText(itemBean.getMainText());
33         }
34     }
35 
36 
37 
38     @Override
39     public int getItemCount() {
40         return mItemsList.size()+1;
41         //return mItemsList.size();
42     }
43 
44     @Override
45     public int getItemViewType(int position) {
46         if (position+1 == getItemCount()) {
47             return TYPE_FOOTER;
48         } else {
49             return TYPE_ITEM;
50         }
51     }
52 
53 
54 
55     class ItemViewHolder extends RecyclerView.ViewHolder {
56         public final TextView mMainTextView;
57         public final TextView mDetailTextView;
58         public ItemViewHolder(View itemView) {
59             super(itemView);
60             mMainTextView = (TextView) itemView.findViewById(R.id.tv_main);
61             mDetailTextView= (TextView) itemView.findViewById(R.id.tv_detail);
62         }
63     }
64 
65     class FooterViewHolder extends RecyclerView.ViewHolder{
66         public final ProgressBar progressBar;
67         public final TextView loadingTips;
68         public FooterViewHolder(View view) {
69             super(view);
70             progressBar = (ProgressBar) view.findViewById(R.id.pull_to_refresh_load_progress);
71             loadingTips = (TextView) view.findViewById(R.id.pull_to_refresh_loading_text);
72         }
73     }
74 }

在返回FooterViewHolder的时候,有一句view.setVisibility(View.GONE); 稍候解释为什么怎么做。

在getItemCount()+1是为了FooterViewHolder预留一个view的位置,到此RecyclerView的改写基本完成,往下就是重点了

 

/////////////////////////////////////////喝口茶的分割线/////////////////////////////////////////

RefreshLayout中,首先肯定是要把getChildView的ListView改成RecyclerView,其中也要替换onScrolled的监听吧。这些就不详细论述了,直接上改变后的代码

    private void getChildView() {
        int childs = getChildCount();
        if (childs > 0) {
            View childView = getChildAt(0);
            if (childView instanceof RecyclerView) {
                mRecyclerView = (RecyclerView) childView;
                // 设置滚动监听器给RecyclerView, 使得滚动的情况下也可以自动加载
                mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                    @Override
                    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                        // 滚动时到了最底部也可以加载更多
                        if (canLoad()) {
                            loadData();
                        }
                    }

                    @Override
                    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                        super.onScrollStateChanged(recyclerView, newState);
                    }
                });
                Log.d(TAG, "### 找到RecyclerView");
            }
        }
    }

第二个变化点,判断是否到了最底部函数isBottom;其中我们必须知道RecyclerView是有横 纵 瀑布等LayoutManager的,我们要恰当的分开处理。

    /*判断是否到了最底部*/
    private boolean isBottom() {
        RecyclerView.LayoutManager layoutManager = null;
        if (mRecyclerView != null) {
            layoutManager = mRecyclerView.getLayoutManager();
        }else{
            return false;
        }

        if(layoutManager instanceof LinearLayoutManager){
            LinearLayoutManager lm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
            int position = lm.findLastVisibleItemPosition();
            int itemCount = lm.getItemCount();
            Log.d(TAG,"current position:"+position);
            Log.d(TAG,"itemCount:"+itemCount);
            if(position+1 == lm.getItemCount()
                    && lm.findViewByPosition(position).getBottom() <= getHeight()){
                Log.d(TAG, "RefreshLayout 滑动到底部了");
                return true;
            }
        }else if(layoutManager instanceof StaggeredGridLayoutManager){
            // http://www.imooc.com/qadetail/91200
            Log.d(TAG, "layoutManager instanceof StaggeredGridLayoutManager not yet implemented");
            Log.d(TAG, "RefreshLayout 滑动到底部了");
        }
        return false;
    }

好了,离完工就差最后一步了,就是setLoading(true/false),我觉得参考链接的博主暴露这个接口真的设计得非常好,完全和原生的swipeRefreshLayout下拉刷新媲美。

也是废话不说,上更改后的代码

    public void setLoading(boolean loading) {
        isLoading = loading;
        LinearLayoutManager lm = (LinearLayoutManager) mRecyclerView.getLayoutManager();
        int position = lm.findLastVisibleItemPosition();
//        int itemCount = mRecyclerView.getLayoutManager().getItemCount();
//        int childCount = mRecyclerView.getLayoutManager().getChildCount();
//        Log.d(TAG,"getChildCount:"+childCount);
//        Log.d(TAG,"getItemCount:"+itemCount);
        View lastView = lm.findViewByPosition(position);
        if (isLoading) {
            lastView.setVisibility(View.VISIBLE);
        } else {
            lastView.setVisibility(View.GONE);
            mDownY = 0;
            mLastY = 0;
        }
    }

来到这里大家应该都明白了之前,在onCreateViewHolder返回FooterViewHolder的时候,有一句view.setVisibility(View.GONE)吧,其实那个加载动画一直都在整个RecyclerView的底部,我只是在恰当的时间隐藏/展示它罢了。

但这里大家必须注意的就是,此时的RecyclerView的itemsize永远是比你实际数据多1的,这点请大家注意!!!重要的话只说一遍。

至于demo,基本上可参照原参考链接的,这里也分享一下近日自己做的一个记账app,简单粗暴。

https://github.com/MrZhaozhirong/MyBill