SwipeRefreshLayout 无法刷新

来源:互联网 发布:数控编程案例 编辑:程序博客网 时间:2024/06/10 02:17

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

附上地址 homepage

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

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

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

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

@Overridepublic 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里


@Overridepublic 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里

@Overridepublic 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。

原创粉丝点击