• SwipeRefreshLayout+RecyclerView 实现上拉追加功能


    参考连接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

  • 相关阅读:
    C# Redis实战(五)
    C# Redis实战(四)
    C# Redis实战(三)
    C# Redis实战(二)
    C# Redis实战(一)
    memcached的基本命令(安装、卸载、启动、配置相关)
    git和tortoisegit安装教程
    编程规范是非常重要的,为什么说可读性比什么都重要?你有没有确定一个编程规范呢?
    关于VR游戏的前景
    在项目开发过程中如何处理人际关系
  • 原文地址:https://www.cnblogs.com/zzrblog/p/5259150.html
Copyright © 2020-2023  润新知