阅读XRecyclerView源码二

学习目标

熟悉和掌握 XRecyclerView 的上拉加载更多功能的实现过程

效果图

这是接着上一篇文章 阅读XRecyclerView源码一,对 XRecyclerView 的下拉加载更多功能的说明。

源码分析

示例图1

LoadingMoreFooter

在自定义的上拉加载更多的控件 LoadingMoreFooter 中,setState(int state) 方法主要是针对上拉加载的各种状态对该控件进行相关操作。

// 设置加载过程状态,及控件的显示与隐藏
    public void setState(int state) {
        switch (state) {
            case STATE_LOADING:
                simpleViewSwitcher.setVisibility(VISIBLE);
                mText.setText(loadingHint);
                this.setVisibility(VISIBLE);
                break;
            case STATE_COMPLETE:
                mText.setText(loadingDownHint);
                this.setVisibility(GONE);
                break;
            case STATE_NOMORE:
                mText.setText(noMoreHint);
                simpleViewSwitcher.setVisibility(GONE);
                this.setVisibility(VISIBLE);
                break;
        }
    }

XRecyclerView

类中的 isLoadingData 参数主要是为了控制在下拉刷新的时候禁止上拉加载,在上拉加载的时候禁止下拉刷新。

关于上拉加载功能的实现,主要是重写 onScrollStateChanged(int state) 方法,在 RecyclerView.SCROLL_STATE_IDLE 状态,获得当前的 lastVisibleItemPosition 这个参数的值,再进行操作。

// 处理加载更多, 主要是 lastVisibleItemPosition
    @Override
    public void onScrollStateChanged(int state) {
        super.onScrollStateChanged(state);
        // SCROLL_STATE_IDLE 状态 滑动停止
        if (state == RecyclerView.SCROLL_STATE_IDLE && mLoadingListener != null && !isLoadingdata) {
            // 获得并判断 LayoutManager,得到最终的 lastVisibleItemPosition
            LayoutManager layoutManager = getLayoutManager();
            int lastVisibleItemPosition;
            if (layoutManager instanceof GridLayoutManager) {
                lastVisibleItemPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
            } else if (layoutManager instanceof StaggeredGridLayoutManager) {
                // 瀑布流布局发现最后的可见 item 位置
                int [] into = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
                ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(into);
                lastVisibleItemPosition = findMax(into);
            } else {
                lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
            }

            // 加载更多的子 view 存在   &&   最后可见的 item 位置 >= adapter 的 items 数量 - 1----当上拉显示到最后一个 item 的时候
            // itemCount 的数量 > XRecyclerView 中子 view 的数量(2 + getHeaderViews())     &&     还有更多加载    &&     下拉刷新头状态没有处在正刷新
            if (layoutManager.getChildCount() > 0 && lastVisibleItemPosition >= layoutManager.getItemCount() - 1
                    && layoutManager.getItemCount() > layoutManager.getChildCount() && !isNoMore &&
                    mRefreshHeader.getState() < ArrowRefreshHeader.STATE_REFRESHING) {
                isLoadingdata = true;
                if (mFootView instanceof LoadingMoreFooter) {
                    ((LoadingMoreFooter) mFootView).setState(LoadingMoreFooter.STATE_LOADING);
                } else {
                    mFootView.setVisibility(VISIBLE);
                }
                mLoadingListener.onLoadMore();
            }
        }
    }

需要注意的是在 RecyclerView 的 LayoutManagerStaggeredGridLayoutManager 时,获取 lastVisibleItemPosition值的方法稍有变化。在获得到 lastVisibleItemPosition 的值后,对它的判断条件稍微多了点,主要就是判断它是不是最后一条 item 数据位置,然后就是对 LoadingMoreFooter 状态设置为 STATE_LOADING,再调用接口的 onLoadMore() 方法,进行具体操作。

loadMoreComplete() 方法

public void loadMoreComplete() {
        isLoadingData =false; // 将加载状态置为 false
        if (mFootView instanceof LoadingMoreFooter) { // 如果是该自定义 LoadingMoreFooter,直接设置状态即可
            ((LoadingMoreFooter) mFootView).setState(LoadingMoreFooter.STATE_COMPLETE);
        } else { // 自己重新定义的 view 则设置隐藏
            mFootView.setVisibility(GONE);
        }
    }

在数据加载完成后,调用这个方法结束加载状态。

setNoMore() 方法

// 设置是否还有更多下拉加载
    public void setNoMore(boolean noMore) {
        isLoadingData = false; // 将加载状态置为 false
        isNoMore = noMore;
        if (mFootView instanceof LoadingMoreFooter) {
            // 根据 noMore 值来设置 LoadingMoreFooter 状态是 NOMORE 还是 COPMPLTETE
            ((LoadingMoreFooter) mFootView).setState(isNoMore ?
                    LoadingMoreFooter.STATE_NOMORE:LoadingMoreFooter.STATE_COMPLETE);
        } else {
            mFootView.setVisibility(GONE);
        }
    }

全部数据加载完成,调用这个方法,改变 LoadingMoreFooter 的加载状态及 UI 显示。

WrapAdapter

WrapAdapter 中,主要是在 getItemViewType()getItemCount() 方法添加了 footView 的返回类型,和增加的 itemCount

@Override
        public int getItemCount() {
            if (loadingMoreEnable) {
                if (adapter != null) {
                    return getHeadersCount() + adapter.getItemCount() + 2;
                } else {
                    return getHeadersCount() + 2;
                }
            } else {
                if (adapter != null) {
                    return getHeadersCount() + adapter.getItemCount() + 1;
                } else {
                    return getHeadersCount() + 1;
                }
            }
        }

        // 设置 ViewType
        @Override
        public int getItemViewType(int position) {
            int adjPosition = position - (getHeadersCount() + 1);
            if (isRefreshHeader(position)) {
                return TYPE_REFRESH_HEADER;
            }
            if (isHeader(position)) {
                position = position - 1;
                return mHeaderTypes.get(position);
            }
            if (isFooter(position)) {
                return TYPE_FOOTER;
            }
            int adapterCount;
            if (adapter != null) {
                adapterCount = adapter.getItemCount();
                if (adjPosition < adapterCount) {
                    int type = adapter.getItemViewType(adjPosition);
                    if (isReservedItemViewType(type)) {
                        throw new IllegalStateException("XRecyclerView require itemViewType in adapter should be less than 10000 " );
                    }
                    return type;
                }
            }

            return 0;
        }

总结

XRecyclerView 的上拉加载功能的实现,通过自定义的 LoadingMoreFooter 类,在该类中添加进了 AVLoadingIndicatorView 控件作为加载时动画效果,暴露 setState(int state) 方法,对上拉加载的不同状态进行对应设置。在 XRecyclerView 类中主要重写 onScrollStateChanged(int state)方法,得到 lastVisibleItemposition 的值,进行加载动作 mLoadingListener.onLoadMore() ,加载完成后调用 loadMoreComplete() 方法,全部数据完成再调用 setNoMore(treu)方法。

Github例子源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值