后篇:自定义(扩展性能强!)的下拉刷新和上拉加载控件

继续上一篇的话题:

前篇:自定义(扩展性能强!)的下拉刷新和上拉加载控件

上一篇结束时提到,功能有些不好的地方,在此篇进行改进。
因为上一篇说了细节,所以这篇着重说修改过的地方。
    /**
     * 可见item高度
     */
    private int visiableItemHeights;

    public void initHeight() {
        hasScroll = false;
        visiableItemHeights = 0;
        getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
                for (int i = 0; i < getChildCount(); i++) {
                    visiableItemHeights += getChildAt(i).getHeight();
                }
            }
        });
    }
在一开始初始化的时候,调用这个方法,目的是为了得到item的总高有没超过屏幕,没有的话,上拉加载就不会出现。

    /**
     * 关闭下拉刷新
     */
    private void closeRefreshing() {
        isLoading = false;
        setSelection(1);
        initHeight();
        if (mState != PULL_REFRESH)
            setState(PULL_REFRESH);
        headerView.setPadding(0, headerHeight, 0, 0);
        if (mCallback != null)
            mCallback.stopRefresh();
    }
重新构造该方法,使其更严谨,多了一处刷新完毕之后,直接显示第一项 (0是头布局)


            case MotionEvent.ACTION_UP:
                isUp = true;
                // 最终位置
                endHeight = -1;
                if (mState == PULL_REFRESH)
                    endHeight = headerHeight;
                else if (mState == LOOSEN_REFRESH)
                    endHeight = 0;

                if (endHeight != -1) {
                    valueAnimator = ValueAnimator.ofInt(headerView.getPaddingTop(), endHeight);
                    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                        @Override
                        public void onAnimationUpdate(ValueAnimator animation) {
                            int padding = (int) animation.getAnimatedValue();
                            lastPadding = padding;
                            float percent = (padding + Math.abs(headerHeight)) * 1.0f / Math.abs(headerHeight);
                            if (mCallback != null) {
                                mCallback.drag(percent, padding - lastPadding);
                            }
                            if (padding < 0) {
                                if (mCallback != null)
                                    mCallback.dragToLoosen(percent, padding - lastPadding);
                            }
                            headerView.setPadding(0, padding, 0, 0);
                        }
                    });
                    valueAnimator.addListener(new SimpleAnimatorListener() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            if (endHeight == 0) {
                                setState(REFRESHING);
                            } else if (endHeight == headerHeight)
                                setState(PULL_REFRESH);
                        }
                    });

                    valueAnimator.setDuration(mDuration);
                    valueAnimator.start();
                }

                break;
        }

手指松开的时候,进行的更严谨的逻辑,避免了endHeight在任意状态都被调用。

    private void setState(int state) {
        if (isLoading)
            state = LOADING;
        switch (state) {
            // 下拉刷新状态
            case PULL_REFRESH:
                if (mState != PULL_REFRESH && headerView != null) {
                    mState = PULL_REFRESH;
                    if (mCallback != null)
                        mCallback.toRullRefresh();
                }
                break;
            // 松开刷新状态
            case LOOSEN_REFRESH:
                if (mState != LOOSEN_REFRESH && headerView != null) {
                    mState = LOOSEN_REFRESH;
                    if (mCallback != null)
                        mCallback.toLoosenRefresh();
                }
                break;
            // 正在刷新状态
            case REFRESHING:
                if (mState != REFRESHING && headerView != null) {
                    mState = REFRESHING;
                    if (mCallback != null)
                        mCallback.toRefreshing();
                }
                break;
            case LOADING:
                if (!isLoading) {
                    footerView.setPadding(0, 0, 0, 0);
                    isLoading = true;
                    if (mState != LOADING && footerView != null) {
                        mState = LOADING;
                        if (mCallback != null)
                            mCallback.toLoading();
                    }
                }
                break;
            default:
                break;
        }
    }

状态修改进行了重构。
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (headerView != null) {
            if (getFirstVisiblePosition() >= 1 && scrollState == OnScrollListener.SCROLL_STATE_FLING) {
                headerView.setPadding(0, headerHeight, 0, 0);
                if (mState == REFRESHING)
                    headerView.setPadding(0, 0, 0, 0);
            }
        }

        if (scrollState == SCROLL_STATE_FLING || scrollState == SCROLL_STATE_TOUCH_SCROLL) {
            if (mCallback!=null)
                mCallback.scroll();
        }

        if (footerView == null || !hasScroll || visiableItemHeights < getHeight())
            return;

        if (getLastVisiblePosition() == getCount() - 1 && mState != REFRESHING && scrollState==SCROLL_STATE_IDLE) {
            if ( !isLoading) {
                setState(LOADING);
                setSelection(getCount());
            }
        }
    }
滑动监听的逻辑都写在了一块,为了根据滑动状态做不同的处理。
所以,另外一个滑动监听的方法就没东西了,是一个空方法。
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

源码下载: https://github.com/q742972035/pullrefreshlvOnlyOneHandler



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值