SwipeRefreshLayout 无法刷新

闲着没事把之前做的一个项目里,首页部分给单挑出来上传到github,首页的内容可以动态的去配置。

附上地址 homepage

今天看一哥们给我提的issue,说banner无法删除。哎,banner还要去掉

想着简单就随手把A实体类给注释掉,运行发现 banner去掉了,但是下拉刷新没了,不执行onRefresh()

swiperefreshlayout没有被干掉,recyclerview也在。一路debug进去,找到onInterceptTouchEvent(MotionEvent ev)方法

打上断点,发现是没有进入switch,直接被false返回了

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    ensureTarget();

    final int action = MotionEventCompat.getActionMasked(ev);
    int pointerIndex;

    if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
        mReturningToStart = false;
    }

    if (!isEnabled() || mReturningToStart || canChildScrollUp()
            || mRefreshing || mNestedScrollInProgress) {
        // Fail fast if we're not in a state where a swipe is possible
        return false;
    }

    switch (action) {
        case MotionEvent.ACTION_DOWN:

再追进canChildScrollUp()里

public boolean canChildScrollUp() {
    if (mChildScrollUpCallback != null) {
        return mChildScrollUpCallback.canChildScrollUp(this, mTarget);
    }
    if (android.os.Build.VERSION.SDK_INT < 14) {
        if (mTarget instanceof AbsListView) {
            final AbsListView absListView = (AbsListView) mTarget;
            return absListView.getChildCount() > 0
                    && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                            .getTop() < absListView.getPaddingTop());
        } else {
            return ViewCompat.canScrollVertically(mTarget, -1) || mTarget.getScrollY() > 0;
        }
    } else {
        return ViewCompat.canScrollVertically(mTarget, -1);
    }
}


ViewCompat.canScrollVertically(mTarget, -1); 返回true

在ViewCompat里


@Override
public boolean canScrollVertically(View v, int direction) {
    return (v instanceof ScrollingView) &&
            canScrollingViewScrollVertically((ScrollingView) v, direction);
}

private boolean canScrollingViewScrollVertically(ScrollingView view, int direction) {
    final int offset = view.computeVerticalScrollOffset();
    final int range = view.computeVerticalScrollRange() -
            view.computeVerticalScrollExtent();
    if (range == 0) return false;
    if (direction < 0) {
        return offset > 0;
    } else {
        return offset < range - 1;
    }
}

终于追到底了,view.computeVerticalScrollOffset() 是返回当前屏幕滑过的距离,第一次进来肯定是0,

view.computeVerticalScrollRange() 是整个View控件的高度,view.computeVerticalScrollExtent() 是当前屏幕显示区域的高度。

正常情况下第一次进来view.computeVerticalScrollRange() 和 view.computeVerticalScrollExtent() 高度一致,所以range为0,

返回false, canChildScrollUp()也是false 这样,在上面的判断里就会继续走到switch里执行。

但是banner被干掉了,也就是swipefreshlayout第一个子view banner高度,在数据初始化时候被定为0dp,

这样view.computeVerticalScrollRange() 和 view.computeVerticalScrollExtent() 高度就不一致range 不等于0,

 canChildScrollUp()返回true。就进入不了switch里面。

解决办法还是有的,我把第一个banner位置让给一个高度只有1dp的布局就行了。

在adapter里

@Override
public int getItemViewType(int position) {
    if (position == 0) {
        if (null != entity.A && entity.A.size() > 0) {
            return TYPE_SLIDER;
        } else {
            return TYPE_REMOVE_SLIDER;
        }
    } 


A 有数据就正常返回banner,没数据就显示那个只有1dp的布局。

具体的实现都在github里。如有其它问题,请给我issue。

猜你喜欢

转载自blog.csdn.net/magicbaby810/article/details/78320856