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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/51473358

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

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

1 思路解析

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

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

mSwipeRfl.setOnRefreshListener(mRefreshListener);

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

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 下面给出源码

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 

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

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

3)暂时没有实现自定义属性,使用起来没有那么方便

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏iOSDevLog

Android 闪屏 Splash

29860
来自专栏腾讯Bugly的专栏

Android ImageView 正确使用姿势

导语 本文主要介绍了ImageView的相关重要方法,从源码角度剖析了一些容易令人混淆或百思不得其解的问题。 一、正确合理使用ImageView 的src 和b...

41580
来自专栏刘望舒

打造一个灵活易用的Banner组件

之前做项目时候出于各种考虑,自己开发了Banner组件FBanner,欢迎大家的Star和PR。github上成熟的轮播图库已经有非常多了,比如banner和A...

14050
来自专栏Android机动车

Android Jetpack 之Navigation Architecture Component使用

activity中fragment默认为NavHostFragment,NavHostFragment通过navGraph与navigation导航编辑器进行关...

44530
来自专栏Android开发指南

11.webview、shareSDK

28460
来自专栏Android知识点总结

1--安卓多媒体之图片综合篇

8320
来自专栏向治洪

Android+struts2+json方式模拟手机登录功能

涉及到的知识点:  1.Struts2框架的搭建(包括Struts2的jSON插件)   2.Android前台访问Web采用HttpClient方式。 ...

25350
来自专栏QQ音乐技术团队的专栏

Android动态布局入门及NinePatchChunk解密

摆脱XML布局文件 相信每一个Android开发者,在接触“Hello World”的时候,就形成了一个观念:Android UI布局是通过layout目录下...

58570
来自专栏developerHaoz 的安卓之旅

Android 撸起袖子,自己封装 DialogFragment

DialogFragment 在 Android 3.0 时被引入,是一种特殊的 Fragment,用于在 Activity 的内容之上显示一个静态的对话框。...

14430
来自专栏图像识别与深度学习

《Android》Lesson04-Menu

21070

扫码关注云+社区

领取腾讯云代金券