Android事件分发 (一)
前言:最近项目中用到了许多事件分发的知识,我也是似懂非懂的样子,但是掌握好事件分发真的很重要,我结合大牛的blog跟自己的理解,决定写一篇博客来记录下自己所学的东西,废话不说了,上代码!!
首先写了一个很简单的布局,里面就放了一个button,给button添加了一个点击事件跟一个触摸事件监听。
mButton=(Button) findViewById(R.id.id_bt);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "onclick----->");
}
});
mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action=event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "ACTION_DOWN----->"+action);
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "ACTION_MOVE----->"+action);
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "ACTION_UP----->"+action);
break;
default:
break;
}
return false;
}
});
}
运行代码后打印的日志为:
06-28 11:13:56.288: I/MainActivity(3355): ACTION_DOWN----->0
06-28 11:13:56.368: I/MainActivity(3355): ACTION_UP----->1
06-28 11:13:56.404: I/MainActivity(3355): onclick----->
也就是说先执行了ontouch方法然后再执行的onclick方法,这是为什么呢?我们看看源码, 首先不管执行的是哪个方法,最先执行的是在View类中的dispatchTouchEvent(MotionEvent event)方法,我们看看它长什么样
*/
public boolean dispatchTouchEvent(MotionEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
return true;
}
if (onTouchEvent(event)) {
return true;
}
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifi
er.onUnhandledEvent(event, 0);
}
return false;
}
捡重点的看,当mOnTouchListener!=null并且控件是enable并且当onTouch返回true的时候,dispatchTouchEvent方法就会返回true,否则就会去执行onTouchEvent方法,
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
return true;
}
if (onTouchEvent(event)) {
return true;
}
}
我们现在的代码是在ontouch方法里面返回的false,我们返回一个true试试,
mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action=event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "ACTION_DOWN----->"+action);
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "ACTION_MOVE----->"+action);
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "ACTION_UP----->"+action);
break;
default:
break;
}
return true;
}
});
结果为:onclick方法不再执行了,我们的点击事件没啦。由此可得知,我们的点击事件是在ontouchevent方法里面执行的,这也说明了前面的结果,ontouch事件优先于ontouchevent事件执行。
06-28 11:24:59.708: I/MainActivity(3532): ACTION_DOWN----->0
06-28 11:24:59.792: I/MainActivity(3532): ACTION_UP----->1
我们得出结论,只有当dispatchTouchEvent方法返回true的时候event的下一个动作才会执行,我们测试一下:我们在ontouch的action_down中返回false,看看action_up还会不会执行
mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int action=event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "ACTION_DOWN----->"+action);
return false;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "ACTION_MOVE----->"+action);
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "ACTION_UP----->"+action);
break;
default:
break;
}
return false;
}
});
结果:
06-28 11:30:52.724: I/MainActivity(3664): ACTION_DOWN----->0
06-28 11:30:52.796: I/MainActivity(3664): ACTION_UP----->1
06-28 11:30:52.820: I/MainActivity(3664): onclick----->
我靠man,这不是误导别人嘛,我刚开始的时候也懵里懵懂的,后面看了源码,还真是这样咯。因为我们这里用的是Button做的测试,我们这回换成ImageView试试,只执行了ACTION_DOWN,那Button为何又可以向下执行呢?带着疑问又看看源码,
结果为:
06-28 11:30:52.724: I/MainActivity(3664): ACTION_DOWN----->0
onTouchEvent源码:不管你干了什么,只要是CLICKABLE 或者是LONG_CLICKABLE的组件,我就直接返回true,也就验证了为什么Button在outouch里面返回了false,事件还是向下传递,因为在onTouchEvent方法里面返回了true,从而dipatchTouchEvent方法返回了true。(如果我们也要像Button一样,不管ontouch返回的是true还是false,事件动作照样传递的话,只需要加上CLICKABLE =true或者LONG_CLICKABLE=true的操作即可)
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
.....
return true;
}
View的事件分发就到此结束了,刚才开始写博客,老手可以略过,^_^!!

本文通过实例演示了Android中事件分发的过程,并解释了点击事件与触摸事件的关系及执行顺序。详细探讨了如何通过返回值控制事件的传递,以及不同组件如Button与ImageView在事件处理上的差异。
1022

被折叠的 条评论
为什么被折叠?



