一、Android 事件响应过程是:先由外向内,再由内向外。
<com.wei.customviews.view.widget.CusLinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.wei.customviews.view.widget.CusRelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.wei.customviews.view.widget.CusImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/mode2"/>
</com.wei.customviews.view.widget.CusRelativeLayout>
</com.wei.customviews.view.widget.CusLinearLayout>
ViewGroup(LinearLayout、RelativeLayout等布局)中代码如下(注:activity及非容器View中是没有拦截函数onInterceptTouchEvent的):
@Override
public boolean onTouchEvent(MotionEvent event)
{
LogUtil.e(TAG, "--- onTouchEvent(MotionEvent event) ---");
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
LogUtil.e(TAG, "--- ACTION_DOWN ---");
break;
case MotionEvent.ACTION_MOVE:
LogUtil.e(TAG, "--- ACTION_MOVE ---");
break;
case MotionEvent.ACTION_UP:
LogUtil.e(TAG, "--- ACTION_UP ---");
break;
case MotionEvent.ACTION_CANCEL:
LogUtil.e(TAG, "--- ACTION_CANCEL ---");
break;
}
// 1.返回false或super.onTouchEvent(event),则表示不响应事件,那么该事件将会不断向上层View的onTouchEvent方法传递,
// 直到某个View的onTouchEvent方法返回true,如果到了最顶层View还是返回false,那么认为该事件不消耗,则在同一个事件系列中,
// 当前View无法再次接收到事件,该事件会交由Activity的onTouchEvent进行处理;
// 2.返回true,自己消耗事件。activity的dispatchTouchEvent及所有上层的dispatchTouchEvent还有onInterceptTouchEvent及
// 自己的dispatchTouchEvent还有onTouchEvent都会被调用;
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
LogUtil.e(TAG, "--- dispatchTouchEvent(MotionEvent ev) ---");
// 1.返回false表示事件不再向下分发,onInterceptTouchEvent及onTouchEvent也不会被调用。
// 事件向上传递(如果本层控件已经是Activity,那么事件将被系统消费或处理);
// 2.返回true,则onInterceptTouchEvent及onTouchEvent不会被调用,上层的onTouchEvent也不会被调用。事件无法被消费
// 3.返回super.dispatchTouchEvent(ev),事件将分发给本层的事件拦截onInterceptTouchEvent 方法进行处理,
// 事件由自己的onTouchEvent决定是否处理;
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
LogUtil.e(TAG, "--- onInterceptTouchEvent(MotionEvent ev) ---");
// 1.返回true表示拦截事件由自己的onTouchEvent处理。能不能处理由onTouchEvent的返回值决定;
// 2.返回false或super.onInterceptTouchEvent(ev)表示不拦截事件,继续向下传播
return super.onInterceptTouchEvent(ev);
}
二、OnTouchListener与OnClickListener :
void initView()
{
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "--- onClick ---");
}
});
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e(TAG, "--- OnTouchListener ---");
return false;
}
});
}
只有我们注册OnTouchListener时重写的 onTouch()方法中
返回false —> 执行onTouchEvent方法 —> 导致onClick()回调方法执行
返回true —> onTouchEvent方法不执行 —> 导致onClick()回调方法不会执行
点击事件分发过程如下 dispatchTouchEvent—->OnTouchListener的onTouch方法—->onTouchEvent–>OnClickListener的onClick方法。也就是说,我们平时调用的setOnClickListener,优先级是最低的,所以,onTouchEvent或OnTouchListener的onTouch方法如果返回true,则不响应onClick方法…