现在写一下总结:
1、为按钮设置onClick点击事件和onTouch触摸事件的执行顺序为:
①、onClick事件:
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TAG", "onClick execute");
}
});
②、onTouch事件:
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("TAG", "onTouch execute, action " + event.getAction());
return false;
}
});
2、执行次序为:
onTouch是优先于onClick执行的,并且onTouch执行了两次,一次是按下ACTION_DOWN,一次是抬起ACTION_UP(你还可能会有多次移动ACTION_MOVE的执行,如果你手抖了一下)。因此事件传递的顺序是先经过onTouch,再传递到onClick。
3、onTouch方法是有返回值的,这里我们返回的是false,表示事件会继续传递;为true表示事件不继续传递了。(可以理解成事件被onTouch消费掉了)
①、只要你触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法(该方法在View中)
dispatchTouchEvent源码为:
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
②、如果条件为真,则执行onTouch(this, event)方法,否则执行的是onTouchEvent(event);
③、三个条件依次是:注册监听 + 控件处于enabled状态 + onTouch方法的返回值(也就是如果这个onTouch回调函数的返回值为true,则执行onTouch而不会执行 onTouchEvent(event),否则执行的是onTouchEvent(event),这就是为什么刚刚说“被消耗掉”了的原因)
5、onClick方法在onTouchEvent(event)方法中,当按钮状态为MotionEvent.ACTION_UP(即点击)时,会执行performClick()方法里回调被点击控件的onClick方方法
我们都知道如果给一个控件注册了touch事件,每次点击它的时候都会触发一系列的ACTION_DOWN,ACTION_MOVE,ACTION_UP等事件。这里需要注意,如果你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action。
touch事件分发的机制总结为:
就拿按钮点击事件为例的touch事件分发的执行过程为:
①、当触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法
②、dispatchTouchEvent方法中首先会执行onTouch这个回调函数,但是执行onTouch这个回调函数有两个前提条件、第一个提前提条件是该控件注册了触摸监听,第二个条件是该控件是的状态是Enable的。
③、onTouch回调函数会有一个返回值,返回这如果为true的话就代表本次触摸事件被消耗掉了,执行接触;返回值为false的话会继续执行onTouchEvent方法。
④、onTouchEvent方法就是真正执行点击事件的地方,也就是我们重写的onClick方法。
⑤、onTouchEvent方法中能够捕获一次点击事件当中ACTION_DOWN、ACTION_ MOVE、ACTION_UP这三个中作,当触摸动作为ACTION_UP会调用onClick方法。
ViewGroup的定义
Android中任何控件都是直接或者间接集成View的,ViewGroup也是一样,ViewGroup可以简单理解成一组View的集合,它里面既可以包含View,也可以包含ViewGroup,譬如说我们熟悉的LinearLayout、RelativeLayout布局就是ViewGroup的子类。
ViewGroup的事件分发举例
1、MyLayout继承LinaerLayout + 两个Button + 设置监听
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的话执行结果为:
4. ViewGroup事件分发的流程
①、Android中touch事件的传递,绝对是先传递到ViewGroup,再传递到View的
②、当你点击了某个控件,首先会去调用该控件所在ViewGroup的dispatchTouchEvent方法,然后在布局的dispatchTouchEvent方法中找到被点击的相应控件,再去调用该控件的dispatchTouchEvent方法。
③、其中会有一个onInterceptTouchEvent方法对事件传递进行拦截,如果返回值为true的话就表示事件不往子View中传递,如果为false的话就表示不对事件传递进行拦截,事件会往子View中传递