android SwipeRefreshLayout使用遇到问题分(二)--滑动冲突

SwipeRefreshLayout布局滑动冲突检测分析

问题现象:

使用SwipeRefreshLayout布局实现下拉刷功能,布局方式是SwipeRefreshLayout嵌套FrameLayout,然后FrameLayout中嵌套ListView。进行下拉刷新往下滑动ListView时,但是ListView没有滑到顶,往下滑动时,但是显示刷新进度条。

分析:

    出现这个现象怀疑是出现滑动冲突之类的问题,所以查看SwipeRefreshLayout的onInterceptTouchEvent查是什么原因引起了这个现象

onInterceptTouchEvent()函数如下:

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

        final int action = MotionEventCompat.getActionMasked(ev);

        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:
                setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true);
                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                mIsBeingDragged = false;
                final float initialDownY = getMotionEventY(ev, mActivePointerId);
                if (initialDownY == -1) {
                    return false;
          .........................................
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                break;
        }

        return mIsBeingDragged;
    }
其中的关键函数为canChildScrollUp这个函数用来检测 SwipeRefreshLayout中嵌套的布局mTarget是否可以滑动。这里mTarget是FrameLayout布局。

然后查看canChildScrollUp函数:

public boolean canChildScrollUp() {
        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);
        }
    }

发现嵌套的 mTarget为AbsListView,ScrollView 或者scrollY大于0下面才会返回false

 if (!isEnabled() || mReturningToStart || canChildScrollUp()
                || mRefreshing || mNestedScrollInProgress) {
            // Fail fast if we're not in a state where a swipe is possible
            return false;
        }
不拦截此次事件,由于mTarget为FrameLayout因此 SwipeRefreshLayout拦截了此次下滑事件,所以便会出现ProgressBar。

结论:

由于mTarget为FrameLayout被SwipeRefreshLayout中的canChildScrollUp检测为不可滑动,所以ListView没有滑到顶却被SwipeRefreshLayout拦截下滑事件。由此提供了一种解决SwipeRefreshLayout滑动冲突的思路即重写canChildScrollUp函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值