这几天了解android的事件分发机制,有了一点感触记录下来:
下面是我参考的网址:
http://blog.csdn.net/guolin_blog/article/details/9097463#reply
http://v.youku.com/v_show/id_XODQ1MjI2MDQ0.html
个人感觉第一篇写的挺好的,但是还有些不足,我在他的基础上进行补充,大家可以看下他的博客,再来看我的。
android的整个事件分发机制流程图:
具体过程我先说明,等下用代码说明:
当点击界面上的button时,产生Action_down事件,会先调用Activity的dispatchTouchEvent()对事件进行检测,然后依次从上往下调用ViewGroup,View的dispatchTouchEvent(), 然后从下往上依次调用onTouchEvent(),如果在向上传递过程中,某一级的onTouchEvent()处理事件并且返回true,那么后面的传递就不会进行了。
代码验证: 这个布局是只有一个自定义的button
public class MainActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("msg","Activity-->onTouchEvent");
return false;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i("msg","Activity-->dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
}
public class MyButton extends Button {
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i("msg","View-->dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("msg","View-->onTouchEvent");
return false;
}
}
public class MyFrameLayout extends FrameLayout {
public MyFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i("msg","ViewGroup-->dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("msg","ViewGroup-->onTouchEvent");
return false;
}
}
当手指按在button上不动,只触发Action_down事件,log如下
当手指up时,输出如下
up相比down只增加了2条,直接执行Activity的dispatchTouchEvent()和onTouchEvent(), 原因就是android系统觉得down事件都消费那么up事件就没必要传递了,直接给Activity执行所以中间有几步直接跳过了。
下面将MyButton中的onTouchEvent()返回值修改为true,消费down事件,得到的结果:
up之后的结果是:
可以看到down和up的结果是一样的,都只执行到了myButton的onTouchEvent()将事件直接消费了,所以后面就没有传递了。
我在这里只是说清了整个整体的流程,如果大家要研究源码细节可以参考这篇:http://blog.csdn.net/guolin_blog/article/details/9097463#reply
这里介绍了dispatchTouchEvent(), onTouch() ,onTouchEvent() 三者之间的具体联系。
除此之外,介绍ViewGroup的onInterceptTouchEvent(), 方法主要是对触发事件进行拦截,让事件无法向后传递,大家在实际操作中ScrollView中含有button,移动button时,触发的是ScrollView的事件,而不是button, 照我上面说的,只要button中的onTouchEvent()进行消费的话,应该会优先执行,但是这里是ScrollView消费的,主要原因是在ScrollView中当监听到Move事件的换,在ScrollView的onInterceptTouchEvent()返回true,对事件进行了拦截,自己进行了处理。 但是如果将ScrollView换成FrameLayout,那么就是另一种结果,FrameLayout的onInterceptTouchEvent()默认返回false,所以可以分发。