android事件冲突

1:简述

所谓的android中的事件冲突:就是view1拦截消耗了本是应该view2消费的事件,前提触摸点在view1和view2范围之内!那么我们必须进行简单了解一下:dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent:三个方法:

这里写图片描述

  • dispatchTouchEvent方法

  是ViewGroup和View对象共有的方法,是事件分发机制执行的方法,简单叙述一下事件分发机制:
  {1}首先父容器ViewGroup在同一个事件序列的MotionEvent.ACTION_DOWN事件中,进行判断是否自身需要拦截:主要通过onInterceptionTouchEvent方法判断是否需要自己拦截,如果拦截:那么如果OnTouchListener设置,进行调用自身的onTouchListener方 法,否则进行调用onTouchEvent方法!

  {2}继而会向下传递给子节点View,进行判断如果OnTouchListener设置,进行调用自身的onTouchListener方法,如果onTouchListener返 回true那么表示消耗了该事件,否则进行调用 onTouchEvent方法,如果onTouchEvent返回true,代表事件已消耗,否则上传给父容器!

  • onInterceptTouchEvent:

  是ViewGroup父容器的方法,而view对象是没有的!父容器主要在该方法里进行是否需要拦截事件的业务逻辑处理!如果在某个事件操作中,判断出返回true,那么会交给自身的OnTouchListener和OnTouchEvent方法!该执行有先后顺序,如果onTouchListener返回true那么表示消耗了该事件,否则进行调用 onTouchEvent方法,如果onTouchEvent返回true,代表事件已消耗,否则上传给父容器!

  • 实例:ViewPager和ScrollView事件冲突
    在一个页面中整体用ScrollView包裹可以竖向的滑动,头部是一个ViewPager的图片轮播相册,在横向滑动轮播相册时,出现滑动不灵敏:在横向滑动时,整体的界面会竖向偏移.显然在横向滑动时,ScrollView拦截了某些事件!
    解决方案:自定义一个MyScrollView复写onInterceptTouchEvent:在按下MotionEvent.ActionDown事件时:交给父容器进行处理(如果不交给父容器处理,拦截效果失败).在MotionEvent.ActionMove事件时,判断横向滑动时,进行拦截事件,交给子容器ViewPager进行处理.

代码
public class HorizontalScrollView extends ScrollView {

    boolean isIntercept;
    public HorizontalScrollView(Context context) {
        super(context);
    }

    public HorizontalScrollView(Context context,    
                  AttributeSet attrs,int defStyle) {
        super(context, attrs, defStyle);
    }

    public HorizontalScrollView(Context context, 
                          AttributeSet attrs) {
        super(context, attrs);
    }

    float startX,startY,moveX,moveY,lastMoveX,lastMoveY;
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch(ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                //进行交给父容器处理
                isIntercept=true;
                startX=ev.getX();
                startY=ev.getY();

            case MotionEvent.ACTION_MOVE:

                //进行位置的赋值
                if(moveX==0 && moveY==0){
                  //进行开始
                    lastMoveX=ev.getX();
                    lastMoveY=ev.getY();
                }else{
                    lastMoveX=moveX;
                    lastMoveY=moveY;
                }
                moveX=ev.getX();
                moveY=ev.getY();

                //如果外部移动的方向:
                if(Math.abs(startX-moveX)>
                        Math.abs(startY-moveY)){
                    //移动的是横向:交给ViewPager处理
                    isIntercept=false;
                }else{
                    //否则交给父容器处理
                    isIntercept=true;
                }

                break;

            case MotionEvent.ACTION_UP:
                break;
        }
        if(isIntercept){
            //true:交给父容器处理
            return super.onInterceptTouchEvent(ev);
        }else{
            //否则交给ViewPager处理
            return isIntercept;
        }
    }
}

  • 实例:ScrollView和RecyclerView事件冲突
    整体的界面用ScrollView包裹,页面中用RecyclerView进行显示列表数据,如果滑动到RecyclerView的列表数据焦点范围内,导致ScrollView不拦截事件,页面的竖直方向就没有惯性滑动了!
    解决方法:自定义一个VerticalScrollView竖向的ScrollView,在竖直方向上拦截事件!

public class VerticalScrollView extends ScrollView{
    public VerticalScrollView(Context context) {
        super(context);
    }

    public VerticalScrollView(Context context, 
                          AttributeSet attrs) {
        super(context, attrs);
    }

    public VerticalScrollView(Context context, 
            AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    float startX,startY;
    float moveX,moveY;
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                startX=event.getRawX();
                startY=event.getRawY();
                break;

            case MotionEvent.ACTION_UP:
                break;

            case MotionEvent.ACTION_MOVE:
                moveY=event.getRawY();
                moveX=event.getRawX();

                //竖直方向上:进行拦截该事件
                if(Math.abs(moveY-startY)>
                            Math.abs(moveX-startX)){
                    //直接返回true
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(event);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值