RecyclerView与SwipeRefreshLayout的完美搭配

SwipeRefreshLayout 是谷歌公司推出的用于下拉刷新的控件,在Version 19.1之后SwipeRefreshLayout 被放到support v4中。我们在前面也已经说过一个SwipeRefreshLayout和ListView实现上拉加载、下拉刷新的例子。而现在RecyclerView也已作为实现列表功能的首选组件,而它本身并没有实现上拉加载、下拉刷新的功能,本节我们就来利用SwipeRefreshLayout 和RecyclerView来实现上拉加载、下拉刷新的功能。
SwipeRefreshLayout 常用的方法如下:
  • setOnRefreshListener(OnRefreshListener):下拉刷新监听器,当用户下拉的时候会触发
  • setRefreshing(boolean):设置SwipeRefreshLayout当前是否处于刷新状态,一般是在请求数据的时候设置为true,在数据被加载到View中后,设置为false。
  • isRefreshing():检查是否处于刷新状态
  • setColorSchemeResources():设置进度条的颜色主题,最多设置四种,以前的setColorScheme()方法已经弃用了。
  • setProgressViewOffset(boolean scale, int start, int end) 调整进度条距离屏幕顶部的距离
布局文件很简单
xml version="1.0" encoding="utf-8"?>
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.xmr.recycleandswiperefresh.MainActivity">

            android:id="@+id/srl_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

                    android:id="@+id/ryv_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    

接着在Activity中获取SwipeRefreshLayout控件并且设置OnRefreshListener监听器,同时实现里边的onRefresh()方法,在该方法中进行网络请求最新数据,然后刷新RecyclerView列表同时设置SwipeRefreshLayout的显示效果。具体代码如下:
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
        //实际项目中这里一般是用网络请求获取数据
        mList.add("下拉刷新");
        mAdapter.notifyDataSetChanged();
        mSwipeRefreshLayout.setRefreshing(false);
    }
});
RecyclerView的实现:
第一种,下拉刷新和上拉刷新都用SwipeRefreshLayout 自带的效果
 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView,
                                             int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE
                        && lastVisibleItem + 1 == mAdapter.getItemCount()) {
                    mSwipeRefreshLayout.setRefreshing(true);
                    //实际项目中这里一般是用网络请求获取数据
                    mList.add("上拉加载");
                    //为了有刷新的效果,延迟关闭刷新效果
                    mSwipeRefreshLayout.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mSwipeRefreshLayout.setRefreshing(false);
                            mAdapter.notifyDataSetChanged();

                        }
                    }, 2000);

                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //判断是当前layoutManager是否为LinearLayoutManager
                // 只有LinearLayoutManager才有查找第一个和最后一个可见view位置的方法
                if (linearLayoutManager instanceof LinearLayoutManager) {
                    //获取最后一个可见view的位置
                    lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                    //获取第一个可见view的位置
//            int firstItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
                }
            }
        });
效果如下:


第二种实现下拉刷新用SwipeRefreshLayout 自带的效果, 上拉加载我们可以给RecyclerView 添加一个类似FooterView的item。
我们在Adapter中实现:
package com.xmr.recycleandswiperefresh;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;

/**
 * Created by Administrator on 2016/9/13.
 */
public class RefreshAdapter1 extends RecyclerView.Adapter {
    private Context mContext;
    private List mDatas;
    private static final int TYPE_ITEM = 0;  //普通Item View

    private static final int TYPE_FOOTER = 1;  //底部FootView
    //已经到底了
    public static final int PULLUP_LOAD_MORE = 0;
    //正在加载中
    public static final int LOADING_MORE = 1;
    //上拉加载状态-默认为0
    private int load_more_status = 0;

    public RefreshAdapter1(Context mContext, List mDatas) {
        this.mContext = mContext;
        this.mDatas = mDatas;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //进行判断显示类型,来创建返回不同的View
        if (viewType == TYPE_ITEM) {
            View view = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.item_recycler_refresh, null);
//            view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
//                    LayoutParams.WRAP_CONTENT));
            return new ItemHolder(view);
        }
        // type == TYPE_FOOTER 返回footerView
        else if (viewType == TYPE_FOOTER) {
            View view = LayoutInflater.from(parent.getContext()).inflate(
                    R.layout.item_recycler_footer, null);
//            view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
//                    LayoutParams.WRAP_CONTENT));
            return new FooterHolder(view);
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof ItemHolder) {
            ItemHolder itemHolder = (ItemHolder) holder;
            itemHolder.textView.setText(mDatas.get(position));
        } else if (holder instanceof FooterHolder) {
            FooterHolder footHolder = (FooterHolder) holder;
            //这句如果不注释,那么底部就会有添加的一个item
            footHolder.linearLayout.setVisibility(View.GONE);
            switch (load_more_status) {
                case PULLUP_LOAD_MORE:
                    footHolder.linearLayout.setVisibility(View.GONE);
//                    footHolder.textView.setText("已经到底了");
                    break;
                case LOADING_MORE:
                    footHolder.linearLayout.setVisibility(View.VISIBLE);
                    footHolder.textView.setText("正在加载更多数据...");
                    break;
            }
        }
    }

    @Override
    public int getItemCount() {
        return mDatas == null ? 0 : mDatas.size() + 1;
    }

    @Override
    public int getItemViewType(int position) {
        // 最后一个item设置为footerView
        if (position + 1 == getItemCount()) {
            return TYPE_FOOTER;
        } else {
            return TYPE_ITEM;
        }
    }

    class ItemHolder extends RecyclerView.ViewHolder {
        public TextView textView;

        public ItemHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv_item_recycler_refresh);
        }
    }

    class FooterHolder extends RecyclerView.ViewHolder {
        public TextView textView;
        public LinearLayout linearLayout;

        public FooterHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv_item_recycler_footer);
            linearLayout = (LinearLayout) itemView.findViewById(R.id.ll_item_recycler_footer);
        }
    }

    /**
     * //上拉加载更多
     * PULLUP_LOAD_MORE=0;
     * //正在加载中
     * LOADING_MORE=1;
     * //加载完成已经没有更多数据了
     * NO_MORE_DATA=2;
     *
     * @param status
     */
    public void changeMoreStatus(int status) {
        load_more_status = status;
        notifyDataSetChanged();
    }
}
而对RecyclerView的上拉加载,我们这样实现:
 mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView,
                                             int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE
                        && lastVisibleItem + 1 == mAdapter.getItemCount()) {
                    Log.i(">>>>>", ">>>>" + lastVisibleItem + ">>>" + mAdapter.getItemCount());
                    mAdapter.changeMoreStatus(mAdapter.LOADING_MORE);
                    //为了有刷新的效果,延迟2s修改状态
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mAdapter.changeMoreStatus(RefreshAdapter1.PULLUP_LOAD_MORE);
                            //实际项目中这里一般是用网络请求获取数据
                            mList.add("上拉加载");
                        }
                    }, 2000);
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //判断是当前layoutManager是否为LinearLayoutManager
                // 只有LinearLayoutManager才有查找第一个和最后一个可见view位置的方法
                if (linearLayoutManager instanceof LinearLayoutManager) {
                    //获取最后一个可见view的位置
                    lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                    //获取第一个可见view的位置
//            int firstItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
                }
            }
        });
    }
最终效果如下:

不过,现在也有点bug,如果列表没有占满屏幕的话,下拉刷新的时候也会同时触发上拉加载的效果,大家如果有好的解决方案的话可以给我说下,先谢谢了
参考:

http://blog.csdn.net/dalancon/article/details/46125667
http://www.cnblogs.com/xiaoyaoxia/p/4977125.html
http://blog.csdn.net/developer_jiangqq/article/details/49992269
http://blog.csdn.net/salute_li/article/details/52118504
http://www.cnblogs.com/csonezp/p/5050324.html

你可能感兴趣的:(Android学习)