SwipeRefreshLayout和ConvenientBanner 事件冲突解决

SwipeRefreshLayout和ConvenientBanner广告轮播事件冲突解决

 

查看布局,分析一下布局,这个布局是很常规的首页布局,一个SwipeRefreshLayout下拉刷新包裹一个带headlistview。其中head头部有个广告轮播的控件,可以左右滑动,下拉刷新是上下滑动。

如果直接使用,你会发现,你左右滑动的时候,很不灵敏,有时候会触动下拉刷新。

 

可以发现淘宝那些广告条,左右滑动非常顺畅,上下滑动下拉刷新也不影响广告轮播。这就是这个博客要解决的一个问题,解决广告条左右滑动和下拉刷新的冲突。

 

我们理想的处理就是,我们只想直接下拉(x方向没有发生很大的变化)就是下拉刷新,其他小动作大动作的左右滑动,都属于广告轮播。


 


这样我们先确定处理事件处理分成2个情况。

A,笔直滑动,x坐标左右变化不大。(下拉刷新)

B,左右滑动,斜滑动(广告条)

 

目标确定了,明确了分2中情况。我们就先从下拉刷新源码入手,因为这样思路比较明确,比较事件传递,先从父类传到子类。那个过程就不再详说了,不明白的可以看一下其他优秀的博客,这篇不错:http://blog.csdn.net/hyp712/article/details/8777835

 

 

查看SwipeRefreshLayout源码,其中onInterceptTouchEvent拦截就是重点


@Override
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;
            }
            mInitialDownY = initialDownY;
            break;

        case MotionEvent.ACTION_MOVE:
            if (mActivePointerId == INVALID_POINTER) {
                Log.e(LOG_TAG, "Got ACTION_MOVE event but don't have an active pointer id.");
                return false;
            }

            final float y = getMotionEventY(ev, mActivePointerId);
            if (y == -1) {
                return false;
            }
            final float yDiff = y - mInitialDownY;
            if (yDiff > mTouchSlop && !mIsBeingDragged) {
                mInitialMotionY = mInitialDownY + mTouchSlop;
                mIsBeingDragged = true;
                mProgress.setAlpha(STARTING_PROGRESS_ALPHA);
            }
            break;

        case MotionEventCompat.ACTION_POINTER_UP:
            onSecondaryPointerUp(ev);
            break;

        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            mIsBeingDragged = false;
            mActivePointerId = INVALID_POINTER;
            break;
    }

    return mIsBeingDragged;
}

上面的一系列逻辑,最后mIsBeingDragged就是返回觉得是否拦截事件,我们就在这个方法入手,我们先判断,如果x坐标变化大于y坐标的变化,那么我们就认为这个是左右滑动的,下拉刷新不处理。(也可以做其他判断,这里测试过x>y效果还不错)

 

我们新建一个自定义view RefreshLayout 继承SwipeRefreshLayout,重新它的onInterceptTouchEvent方法。

(就是下面这几行代码,返回false然后下拉刷新控件不执行onTouchEvent事件)

float lastx = 0;
float lasty = 0;
boolean ismovepic = false;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {



    if (ev.getAction() ==MotionEvent.ACTION_DOWN){
        lastx = ev.getX();
        lasty = ev.getY();
        ismovepic = false;
        return super.onInterceptTouchEvent(ev);
    }

    final int action = MotionEventCompat.getActionMasked(ev);
    VLog.v(ev.getX() + "---" + ev.getY());

    int x2 = (int) Math.abs(ev.getX() - lastx);
    int y2 = (int) Math.abs(ev.getY() - lasty);

    //滑动图片最小距离检查
    VLog.v("滑动差距 - >" + x2 + "--" + y2);
    if (x2>y2){
        if (x2>=100)ismovepic = true;
        return false;
    }

    //是否移动图片(下拉刷新不处理)
    if (ismovepic){
        VLog.v("滑动差距 - >" + x2 + "--" + y2);
        return false;
    }

    boolean isok = super.onInterceptTouchEvent(ev);

    VLog.v("isok ->" + isok);

    return isok;
}


上面判断,为了效果更好,加入了ismovepic 判断,这个判断也很简单,就是如果我按住图片,然后左右滑动一点点,然后一直下拉,超出了广告条的位置,这样的话,广告条处理不了超出位置的点击事件,就有个bug,下拉刷新会再次出现。所以如果设置它左右滑动后,y坐标变化就算超过100(100可以自由设置,我这里先定100,测试效果还不错),也就是脱离广告条位置,我们也不能让下拉刷新出现。

 

加入这个判断后,手势划来划去都非常灵敏。


ps:按照这个思路,其实其他的下拉刷新控件,大致的事件冲突解决方案思路也差不多,有更好的方法可以留言讨论一下。


睡觉了,一点多了,技术一点点积累中




  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值