Android 3步搞定事件分发机制,再也不用担心onTouch和onTouchEvent&dispatchTouchEvent

1.Android 3步搞定事件分发机制,再也不用担心onTouch和onTouchEvent&dispatchTouchEvent

https://blog.csdn.net/WHB20081815/article/details/62888575

2.Android 滑动冲突的完美解决方案 listview和scroView

https://blog.csdn.net/WHB20081815/article/details/88617041

3.Android 深入理解 View 的绘制流程和机制

https://blog.csdn.net/WHB20081815/article/details/62236641

4.Android 5.0 6.0 以及7.0新特性 MD风格 敏感权限 文件访问

https://blog.csdn.net/WHB20081815/article/details/70244065

5.Android 万能适配方案和UI屏幕适配 不同分辨率 最全面 最易懂的

https://blog.csdn.net/WHB20081815/article/details/76937801

6.Android 2分钟刷Android 8.0系统 和 8.0适配 完美方案

https://blog.csdn.net/WHB20081815/article/details/75669925

7.Android快速理解Activity、View及Window&WindowManager之间关系

https://blog.csdn.net/WHB20081815/article/details/62419059

       事件分发机制分为2种:View事件的分发和ViewGroup事件分发机制

先看简单的View事件分发机制

//子控件的ontouch方法影响子控件的函数
//onTouch====onTouchEvent====onClick;
/**
 * 检验view的事件分发顺序,点击---dispatch-  Ontouch返回值为ture  不执行---ontouchEvent---onclick
 */
button1.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("TAG", "button1  on touch"+event.getAction());
        return true;
    }
});

/**
 * 检验view的事件分发顺序, 点击---dispatch-  Ontouch返回值为false执行---ontouchEvent---onclick
 */
button2.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("TAG", "button1  on touch" + event.getAction());
        return false;
    }
});

 

然后我们来看一下View中dispatchTouchEvent方法的源码:

 

public boolean dispatchTouchEvent(MotionEvent event) {
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
            mOnTouchListener.onTouch(this, event)) {
        return true;
    }
    return onTouchEvent(event);
}

 

 

1、整个View的事件转发流程是:

View.dispatchEvent->View.setOnTouchListener->View.onTouchEvent

在dispatchTouchEvent中会进行OnTouchListener的判断,如果OnTouchListener不为null且返回true,则表示事件被消费,onTouchEvent不会被执行;否则执行onTouchEvent。

onClick方法是在onTouchEvent方法里调用的

 

2个Button的onTouch返回值验证了以下:

onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。

假如onTouch方法返回false会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。

 

Button和ImageView效果不一样:一个是自带点击,一个是要自己控制点击

onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。因此如果你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实现。

/**ImageView默认是不能点击事件的,要想点击的话必须手动设置*/
imageView.setClickable(true);

imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.e("TAG","imageView setOnTouchListener");
    }
});
 
 

ViewGruop的事件分发:

多了一个拦截事件的方法:onInterceptTouchEvent

 

比较好的形容:

其中Activity和View控件(TextView)拥有分派和处理事件方法,View容器(LinearLayout)具有分派,拦截,处理事件方法。

这里也有个比喻:领导都会把任务向下分派,一旦下面的人把事情做不好,就不会再把后续的任务交给下面的人来做了,只能自己亲自做,

如果自己也做不了,就只能告诉上级不能完成任务,上级又会重复他的过程。

另外,领导都有权利拦截任务,对下级隐瞒该任务,而直接自己去做,如果做不成,也只能向上级报告不能完成任务。

 

/**默认为false,不拦截子控件的监听*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return false;
}

 

public boolean dispatchTouchEvent(MotionEventev);  //用来分派event
public boolean onInterceptTouchEvent(MotionEventev);//用来拦截event
public boolean onTouchEvent(MotionEventev);//用来处理event

总结:

1. Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。

2. 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。

3.拦截的好好处在于调用谁的dispatchTouchEvent的方法,谁出来点击事件

4. 子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。

5.在ViewGroup中onInterceptTouchEvent方法若反回false,那么触屏事件会继续向下传递,

但如果没有子View去处理这个事件,即子view的onTouchEvent没有返回True

则最后还是由ViewGroup去处理这个事件,也就又执行了自己的onTouchEvent。

 

下面是方法总结:

OnTouch方法是在Activity里面设置的监听事件

1. onTouch和onTouchEvent有什么区别,又该如何使用?

从源码中可以看出,这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行。

 

思考的问题:

1.View的dispatchTouchEvent重写了会怎么样,View的onTouchEvent重写了会怎样?

2.ViewGroup的dispatchTouchEvent重写了会怎么样,ViewGroup的onTouchEvent重写了会怎样?

3.ListView上的button,点击button2个控件同时要有相应,应该怎么处理?

4.

事件的传递顺序:

 

G----->A----->B----->C----->D----->E----->F

AS源代码不知道什么原因传不上去委屈

 

参考博客:

http://blog.csdn.net/guolin_blog/article/details/9097463

http://blog.csdn.net/lmj623565791/article/details/38960443

事件分发机制分为2种:View事件的分发和ViewGroup事件分发机制

先看简单的View事件分发机制

//子控件的ontouch方法影响子控件的函数
//onTouch====onTouchEvent====onClick;
/**
 * 检验view的事件分发顺序,点击---dispatch-  Ontouch返回值为ture  不执行---ontouchEvent---onclick
 */
button1.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("TAG", "button1  on touch"+event.getAction());
        return true;
    }
});

/**
 * 检验view的事件分发顺序, 点击---dispatch-  Ontouch返回值为false执行---ontouchEvent---onclick
 */
button2.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("TAG", "button1  on touch" + event.getAction());
        return false;
    }
});

 

然后我们来看一下View中dispatchTouchEvent方法的源码:

 

public boolean dispatchTouchEvent(MotionEvent event) {
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
            mOnTouchListener.onTouch(this, event)) {
        return true;
    }
    return onTouchEvent(event);
}

 

 

1、整个View的事件转发流程是:

View.dispatchEvent->View.setOnTouchListener->View.onTouchEvent

在dispatchTouchEvent中会进行OnTouchListener的判断,如果OnTouchListener不为null且返回true,则表示事件被消费,onTouchEvent不会被执行;否则执行onTouchEvent。

onClick方法是在onTouchEvent方法里调用的

 

2个Button的onTouch返回值验证了以下:

onTouchListener的onTouch方法优先级比onTouchEvent高,会先触发。

假如onTouch方法返回false会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。

 

Button和ImageView效果不一样:一个是自带点击,一个是要自己控制点击

onTouch能够得到执行需要两个前提条件,第一mOnTouchListener的值不能为空,第二当前点击的控件必须是enable的。因此如果你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实现。

/**ImageView默认是不能点击事件的,要想点击的话必须手动设置*/
imageView.setClickable(true);

imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.e("TAG","imageView setOnTouchListener");
    }
});
 
 

ViewGruop的事件分发:

多了一个拦截事件的方法:onInterceptTouchEvent

 

比较好的形容:

其中Activity和View控件(TextView)拥有分派和处理事件方法,View容器(LinearLayout)具有分派,拦截,处理事件方法。

这里也有个比喻:领导都会把任务向下分派,一旦下面的人把事情做不好,就不会再把后续的任务交给下面的人来做了,只能自己亲自做,

如果自己也做不了,就只能告诉上级不能完成任务,上级又会重复他的过程。

另外,领导都有权利拦截任务,对下级隐瞒该任务,而直接自己去做,如果做不成,也只能向上级报告不能完成任务。

 

/**默认为false,不拦截子控件的监听*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return false;
}

 

public boolean dispatchTouchEvent(MotionEventev);  //用来分派event
public boolean onInterceptTouchEvent(MotionEventev);//用来拦截event
public boolean onTouchEvent(MotionEventev);//用来处理event

 

 

 

总结:

1. Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。

2. 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。

3.拦截的好好处在于调用谁的dispatchTouchEvent的方法,谁出来点击事件

4. 子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。

5.在ViewGroup中onInterceptTouchEvent方法若反回false,那么触屏事件会继续向下传递,

但如果没有子View去处理这个事件,即子view的onTouchEvent没有返回True

则最后还是由ViewGroup去处理这个事件,也就又执行了自己的onTouchEvent。

 

下面是方法总结:

OnTouch方法是在Activity里面设置的监听事件

 

 

1. onTouch和onTouchEvent有什么区别,又该如何使用?

从源码中可以看出,这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行。如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行。

 

思考的问题:

1.View的dispatchTouchEvent重写了会怎么样,View的onTouchEvent重写了会怎样?

2.ViewGroup的dispatchTouchEvent重写了会怎么样,ViewGroup的onTouchEvent重写了会怎样?

3.ListView上的button,点击button2个控件同时要有相应,应该怎么处理?

4.

 

事件的传递顺序:

 

G----->A----->B----->C----->D----->E----->F

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值