Andorid 中TouchEvent理解(四)滑动冲突的解决

理解了TouchEvent之后,就是为了更好的解决滑动冲突。网上找到两种的解决办法,因为不一定非要固定的方法解决,就先记录这两种方式,并写了个小Demo.

转载自 http://blog.csdn.net/a992036795/article/details/51735501 

解决横竖滑动冲突,水平也是一样的,只是判定条件就需要根据具体情况来处理了。

1)外部拦截解决,在ViewGroup来决定传递来的事件由自己处理还是交给ChildView来处理。修改parentView就可了。

/**
     * 拦截事件
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();

        switch (ev.getAction()) {
            /*如果拦截了Down事件,则子类不会拿到这个事件序列*/
            case MotionEvent.ACTION_DOWN:
                lastXIntercept = x;
                lastYIntercept = y;
                intercepted = false;
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                    intercepted = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                final int deltaX = x - lastXIntercept;
                final int deltaY = y - lastYIntercept;
                /*根据条件判断是否拦截该事件*/
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                intercepted = false;
                break;

        }
        lastXIntercept = x;
        lastYIntercept = y;
        return intercepted;
    }

关键部分就是重写onInterceptTouchEvent这个方法,来完成拦截,这里在Down的时候,没有拦截事件,这样就能够找到TargetView,可以将事件传递到target,但是在MOVE的时候写了逻辑,需要拦截条件:


X方向上的滑动大于Y方向的滑动的就返回true自己处理,切换LIstView。

X方向上的滑动小于Y方向的滑动就返回false交由ListView处理,ListView上下滚动。



2)内部拦截解决,在parentView中,拦截逻辑如下:


 /**
     * 拦截事件
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
                return true;
            }
            return false;
        } else {
            return true;
        }
    }

Down事件不拦截,就可以找打targetView,后续的事件才有机会传递下去,其他事件统一都拦截掉,ChildView的修改如下。

/**
     * 使用 outter.requestDisallowInterceptTouchEvent();
     * 来决定父控件是否对事件进行拦截
     *
     * @param ev
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mHorizontalEx2.requestDisallowInterceptTouchEvent(true);    //设置标记为不parent让拦截
                break;
            case MotionEvent.ACTION_MOVE:
                final int deltaX = x - lastXIntercepted;
                final int deltaY = y - lastYIntercepted;
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    mHorizontalEx2.requestDisallowInterceptTouchEvent(false);   //设置标记为让parent拦截
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        lastXIntercepted = x;
        lastYIntercepted = y;
        return super.dispatchTouchEvent(ev);
    }

在ViewGroup中,贴一段代码

if (actionMasked == MotionEvent.ACTION_DOWN
                    || mFirstTouchTarget != null) {
                final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
                if (!disallowIntercept) {
                    intercepted = onInterceptTouchEvent(ev);
                    ev.setAction(action); // restore action in case it was changed
                } else {
                    intercepted = false;
                }
            } else {
                // There are no touch targets and this action is not an initial down
                // so this view group continues to intercept touches.
                intercepted = true;
            }

这里当时其他的事件的时候由于targe!=null,可以在这里根据Flag决定是否调用这个拦截函数。

requestDisallowInterceptTouchEvent(true)就是设置的mFlag,为FLAGDISALL_DISALLOW_INTERCETP,上面的parentView中的重写之后,当其他事件只要调用就是拦截下来,由parent处理。

targetView中定义逻辑,当

X方向上的滑动大于Y方向的滑动就让parent拦截下来,parent处理

X方向上的滑动小于Y方向的滑动就不让parent拦截下来,自己处理

这样在View内部就可以干涉到parent的事件处理过程。来决定谁来处理这些事件



demo地址点击打开链接


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值