button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "onClick execute");
}
});
2、onTouch事件:
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "onTouch execute, action " + event.getAction());
return false;
}
});
3、执行次序为:
onTouch是优先于onClick执行的,并且onTouch执行了两次,一次是按下ACTION_DOWN,一次是抬起ACTION_UP(你还可能会有多次移动ACTION_MOVE的执行,如果你手抖了一下)。因此事件传递的顺序是先经过onTouch,再传递到onClick。
4、onTouch方法是有返回值的,这里我们返回的是false,表示事件会继续传递;为true表示事件不继续传递了。(可以理解成事件被onTouch消费掉了)
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
1、如果条件为真,则执行onTouch(this, event)方法,否则执行的是onTouchEvent(event);
3、三个条件依次是:注册监听 + 控件处于enabled状态 + onTouch方法的返回值(也就是如果这个onTouch回调函数的返回值为true,则执行onTouch而不会执行 onTouchEvent(event),否则执行的是onTouchEvent(event),这就是为什么刚刚说“被消耗掉”了的原因)
3、onClick方法在onTouchEvent(event)方法中,当按钮状态为MotionEvent.ACTION_UP(即点击)时,会执行performClick()方法里回调被点击控件的onClick方方法
myLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "myLayout on touch");
return false;
}
});
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "You clicked button1");
}
});
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "You clicked button2");
}
});
2、分别点击的结果为:
即当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。
可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。
3、ViewGroup中有一个onInterceptTouchEvent方法
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
如果重写这个方法,返回true的话执行结果为:
3. ViewGroup事件分发的流程
1、Android中touch事件的传递,绝对是先传递到ViewGroup,再传递到View的
2、当你点击了某个控件,首先会去调用该控件所在ViewGroup的dispatchTouchEvent方法,然后在布局的dispatchTouchEvent方法中找到被点击的相应控件,再去调用该控件的dispatchTouchEvent方法。
3、其中会有一个onInterceptTouchEvent方法对事件传递进行拦截,如果返回值为true的话就表示事件不往子View中传递,如果为false的话就表示不对事件传递进行拦截,事件会往子View中传递