前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RecycleView下拉刷新控件的封装(包括下拉刷新和加载更多 )

RecycleView下拉刷新控件的封装(包括下拉刷新和加载更多 )

作者头像
程序员徐公
发布2018-09-18 17:06:29
1.7K0
发布2018-09-18 17:06:29
举报
文章被收录于专栏:程序员开发工具

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1341934

最近学习了RecycleView控件的使用,就尝试封装了RecycleView 下拉刷新控件,实现的功能有(下拉刷新和加载更多)

转载请注明原博客地址:http://blog.csdn.net/gdutxiaoxu/article/details/51473358

1 思路解析

1)我是通过继承LinearLayout来实现的,里面拥有SwipeRefreshLayout和RecycleView

2)下拉刷新是通过SwipeRefreshLayout设置监听器实现的

代码语言:javascript
复制
代码语言:javascript
复制
mSwipeRfl.setOnRefreshListener(mRefreshListener);

3)加载更多是通过监听RecycleView的OnScrollListener

代码语言:javascript
复制
mScrollListener = new RecyclerView.OnScrollListener() {

    private int mLastVisibleItem;
    private int mDy;

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (newState != RecyclerView.SCROLL_STATE_IDLE) {
            return;
        }
        //最后显示的项
        mLastVisibleItem = mLayoutManager.findLastCompletelyVisibleItemPosition();
        int totalItemCount = mLayoutManager.getItemCount();
        /**
         * 只有在下拉,并且没有早加载更多,并且允许加载更多,并且在最后一个条目,才调用加载更多的接口
         */
        if (mDy >= 0 && !isLoadMore && (mLastVisibleItem >= totalItemCount - 1) &&
                enableLoadMore) {
            loadMore();
        }
    }

2 下面给出源码

代码语言:javascript
复制
public class PulltoRefreshRecyclerView extends LinearLayout {

    String Tag = "xujun";

    /**
     * 内容控件
     */
    private RecyclerView mRecyclerView;
    /**
     * 刷新布局控件
     */
    private SwipeRefreshLayout mSwipeRfl;
    private LinearLayoutManager mLayoutManager;
    /*
     * 刷新布局的监听
     */
    private OnRefreshListener mRefreshListener;
    /**
     * 内容控件滚动监听
     */
    private RecyclerView.OnScrollListener mScrollListener;

    /*
     * 刷新加载监听事件
     */
    private onRefreshListener mRefreshLoadMoreListner;

    /**
     * 是否正在刷新
     */
    private boolean isRefresh = false;
    /**
     * 是否正在加载更多
     */
    private boolean isLoadMore = false;
    private FrameLayout mFootView;
    //    是否允许加载更多
    private boolean enableLoadMore = true;
    private int mMeasuredHeight;

    public PulltoRefreshRecyclerView(Context context) {
        this(context, null);
    }

    @SuppressWarnings("deprecation")
    public PulltoRefreshRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 导入布局
        initView(context);


        /**
         * 监听上拉至底部滚动监听
         */
        initListener();
        mRecyclerView.setHasFixedSize(true);
        mLayoutManager = new LinearLayoutManager(context);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setOnScrollListener(mScrollListener);
    }

    private void setFootViewHeight(int height) {
        ViewGroup.LayoutParams layoutParams = mFootView.getLayoutParams();
        layoutParams.height = height;
        mFootView.setLayoutParams(layoutParams);
    }

    private void initListener() {
        mScrollListener = new RecyclerView.OnScrollListener() {

            private int mLastVisibleItem;
            private int mDy;

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState != RecyclerView.SCROLL_STATE_IDLE) {
                    return;
                }

                //最后显示的项
                mLastVisibleItem = mLayoutManager.findLastCompletelyVisibleItemPosition();

                int totalItemCount = mLayoutManager.getItemCount();

                /**
                 * 只有在下拉,并且没有早加载更多,并且允许加载更多,并且在最后一个条目,才调用加载更多的接口
                 */
                if (mDy >= 0 && !isLoadMore && (mLastVisibleItem >= totalItemCount - 1) &&
                        enableLoadMore) {
                    loadMore();


                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                mDy = dy;
            }

        };

        /**
         * 下拉至顶部刷新监听
         */
        mRefreshListener = new OnRefreshListener() {

            @Override
            public void onRefresh() {
            /*    Log.i("Tag", "onRefresh1");
                Log.i("Tag", isRefresh + "");
                Log.i("Tag", isRefresh + "");
                Log.i("Tag", isLoadMore + "");*/
                LUtils.i("isLoadMore=" + isLoadMore);
                if (!isRefresh && !isLoadMore) {//没有正在刷新或者正在加载更多
                    isRefresh = true;
                    refresh();
                }
            }
        };
        mSwipeRfl.setOnRefreshListener(mRefreshListener);
    }

    private void initView(Context context) {
        View.inflate(context, R.layout.pulltorefreshrecyclerview,this);
        mSwipeRfl = (SwipeRefreshLayout) findViewById(R.id.all_swipe);
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        initFootView();


    }

    private void initFootView() {
        mFootView = (FrameLayout) findViewById(R.id.ll_load_more);
        LUtils.i("mFootView=" +(mFootView==null));
        mFootView.measure(0, 0);
        mMeasuredHeight = mFootView.getMeasuredHeight();
        setFootViewHeight(0);

    }


    public void setFooterView(View view) {
        if (getFooterView() != null) {
            getFooterView().removeAllViews();
            mFootView.addView(view);
        }

    }

    public FrameLayout getFooterView() {
        return mFootView;
    }

    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public void setLayoutManager(LayoutManager layoutManager) {
        if (mRecyclerView != null) {
            mRecyclerView.setLayoutManager(layoutManager);
        }
    }

    /**
     * 设置是否允许下拉刷新
     *
     * @param enable
     */
    public void setPullRefreshEnable(boolean enable) {
        setRefreshEnabled(enable);
    }

    public boolean getPullRefreshEnable() {
        return mSwipeRfl.isEnabled();
    }

    public void setLoadMoreListener() {
        mRecyclerView.setOnScrollListener(mScrollListener);
    }

    public void loadMore() {
        if (mRefreshLoadMoreListner != null) {
            isLoadMore = true;
            //设置在加载更多的时候swipeLayout不允许加载更多,同时需要设置在加载更多完毕的时候允许swipeLayout加载更多
            setRefreshEnabled(false);
            mLayoutManager.scrollToPosition(mLayoutManager.findLastVisibleItemPosition());
            showFootView();
            mRefreshLoadMoreListner.onLoadMore(mRecyclerView);

        }
    }

    public void setRefreshEnabled(boolean enabled) {
        mSwipeRfl.setEnabled(enabled);
    }

    private void showFootView() {
        setFootViewHeight(mMeasuredHeight);

    }

    public void OnRefreshCompleted() {
        if (isRefresh) {//如果是正在刷新,就调用这个方法
            stopRefresh();
        } else if (isLoadMore) {//如果是正在加载更多,就调用这个方法
            setLoadMoreCompleted();
        }


    }

    /**
     * 加载更多完毕,为防止频繁网络请求,isLoadMore为false才可再次请求更多数据
     */
    private void setLoadMoreCompleted() {

//因为在加载更多的时候设置swipeLayout不允刷新,
// 所以加载更多完毕的时候需要设置允许swipeLayout允许刷新
        setRefreshEnabled(true);
        isLoadMore = false;
        hideFootView();
    }

    private void hideFootView() {
//        setFootViewHeight(0);
        rollbackFootView(mFootView);
    }

    private void stopRefresh() {
        isRefresh = false;
        mSwipeRfl.setRefreshing(false);

    }

    public void setOnRefreshListener(onRefreshListener listener) {
        mRefreshLoadMoreListner = listener;
    }

    public void refresh() {
        if (mRefreshLoadMoreListner != null) {
            mRefreshLoadMoreListner.onRefresh(mRecyclerView);
        }
    }

    public void setAdapter(RecyclerView.Adapter adapter) {
        if (adapter != null)
            mRecyclerView.setAdapter(adapter);
    }

    public interface onRefreshListener {

        public void onRefresh(RecyclerView recyclerView);

        public void onLoadMore(RecyclerView recyclerView);
    }

    /**
     * 回滚下拉刷新头部控件
     */
    private void rollbackFootView(View view) {

        final ValueAnimator rbAnimator = ValueAnimator.ofInt(0, mMeasuredHeight);
        rbAnimator.setDuration(800);
        rbAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        rbAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float animatedFraction = animation.getAnimatedFraction();

                /**
                 * 当刷新完毕后,进行headerView的隐藏
                 */
                setFootViewHeight((int) (mMeasuredHeight - animatedFraction * mMeasuredHeight));
            }


        });
        rbAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                rbAnimator.removeAllListeners();
            }
        });
        rbAnimator.start();

    }

    public boolean isLoadMore() {
        return isLoadMore;
    }

    public boolean isRefresh() {
        return isRefresh;
    }

    public boolean isEnableLoadMore() {
        return enableLoadMore;
    }
}

3 存在的问题

1)在判断是够加载更多的时候 需要mLastVisibleItem 

代码语言:javascript
复制
/**
 * 只有在下拉,并且没有早加载更多,并且允许加载更多,并且在最后一个条目,才调用加载更多的接口
 */
if (mDy >= 0 && !isLoadMore && (mLastVisibleItem >= totalItemCount - 1) &&
        enableLoadMore) {
    loadMore();
}
代码语言:javascript
复制
//最后显示的项
mLastVisibleItem = mLayoutManager.findLastCompletelyVisibleItemPosition();
但是findLastCompletelyVisibleItemPosition()这个方法是LinearLayoutManger里面的 方法 ,
LinearLayoutManger的父类里面 RecyclerView.LayoutManager
没有这个方法findLastCompletelyVisibleItemPosition();
这样导致我们 无法动态更改我们当前RecycleView实例的 LayoutManger
代码语言:javascript
复制
2)暂时没有实现SwipeLayoutProgress下拉刷新显示进度条 离我们第一个item之间的距离,可以参考

http://www.cnblogs.com/sunzn/p/3795009.html

代码语言:javascript
复制
3)暂时没有实现自定义属性,使用起来没有那么方便

4)源码下载地址https://github.com/gdutxiaoxu/RecycleViewDemo

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年05月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档