一。案例分析
还是和上文一样,写一个非常简单的项目。
我们自定义了一个LinearLayout和Button控件。
由代码中,我们可以发现LinearLayout比Button多了一个onInterceptTouchEvent()方法。
MyLinearLayout.java
package com.example.viewanalyse;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyLinearLayout extends LinearLayout {
private static final String TAG = "ViewAnalyse";
public MyLinearLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
Log.d(TAG, "dispatchTouchEvent-- action="+ev.getAction()+"--MyLinearLayout");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
Log.d(TAG, "onInterceptTouchEvent-- action="+ev.getAction()+"--MyLinearLayout");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.d(TAG, "onTouchEvent-- action="+event.getAction()+"--MyLinearLayout");
return super.onTouchEvent(event);
}
}
MyButton.java
package com.example.viewanalyse;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.widget.Button;
public class MyButton extends Button {
private static final String TAG = "ViewAnalyse";
public MyButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.d(TAG, "onTouchEvent-- action="+event.getAction()+"--MyButton");
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d(TAG, "dispatchTouchEvent-- action="+event.getAction()+"--MyButton");
// TODO Auto-generated method stub
super.dispatchTouchEvent(event);
return true;
}
}
布局文件activity_main.xlm
MainActivity.java
package com.example.viewanalyse;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
public class MainActivity extends Activity implements View.OnTouchListener,View.OnClickListener {
private MyLinearLayout mLayout;
private Button mButton;
private static final String TAG = "ViewAnalyse";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayout =(MyLinearLayout)findViewById(R.id.layout);
mButton =(MyButton)findViewById(R.id.button);
mLayout.setOnTouchListener(this);
mButton.setOnTouchListener(this);
mLayout.setOnClickListener(this);
mButton.setOnClickListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
Log.d(TAG, "onTouch-- action="+event.getAction()+" --"+v);
return false;
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.d(TAG, "onClick --"+v);
}
}
1.1 我们用手指点击一下button,打印出来的log:
10-16 11:32:41.410: D/ViewAnalyse(10616): dispatchTouchEvent-- action=0--MyLinearLayout
10-16 11:32:41.410: D/ViewAnalyse(10616): onInterceptTouchEvent-- action=0--MyLinearLayout
10-16 11:32:41.410: D/ViewAnalyse(10616): dispatchTouchEvent-- action=0--MyButton
10-16 11:32:41.410: D/ViewAnalyse(10616): onTouch-- action=0 --com.example.viewanalyse.MyButton
10-16 11:32:41.410: D/ViewAnalyse(10616): onTouchEvent-- action=0--MyButton
10-16 11:32:41.460: D/ViewAnalyse(10616): dispatchTouchEvent-- action=1--MyLinearLayout
10-16 11:32:41.460: D/ViewAnalyse(10616): onInterceptTouchEvent-- action=1--MyLinearLayout
10-16 11:32:41.460: D/ViewAnalyse(10616): dispatchTouchEvent-- action=1--MyButton
10-16 11:32:41.460: D/ViewAnalyse(10616): onTouch-- action=1 --com.example.viewanalyse.MyButton
10-16 11:32:41.460: D/ViewAnalyse(10616): onTouchEvent-- action=1--MyButton
10-16 11:32:41.470: D/ViewAnalyse(10616): onClick --com.example.viewanalyse.MyButton
1.2 我们用手指点击一下除button以外的其他区域(ViewGroup事件派发),打印出来的log:
10-16 11:35:04.260: D/ViewAnalyse(10616): dispatchTouchEvent-- action=0--MyLinearLayout
10-16 11:35:04.260: D/ViewAnalyse(10616): onInterceptTouchEvent-- action=0--MyLinearLayout
10-16 11:35:04.260: D/ViewAnalyse(10616): onTouch-- action=0 --com.example.viewanalyse.MyLinearLayout
10-16 11:35:04.260: D/ViewAnalyse(10616): onTouchEvent-- action=0--MyLinearLayout
10-16 11:35:04.320: D/ViewAnalyse(10616): dispatchTouchEvent-- action=1--MyLinearLayout
10-16 11:35:04.320: D/ViewAnalyse(10616): onTouch-- action=1 --com.example.viewanalyse.MyLinearLayout
10-16 11:35:04.320: D/ViewAnalyse(10616): onTouchEvent-- action=1--MyLinearLayout
10-16 11:35:04.330: D/ViewAnalyse(10616): onClick --com.example.viewanalyse.MyLinearLayout
由Log1.1 我们可以发现,点击一下button,首先触发的是Linearlayout中的dispatchTouchEvent() -->LinearLayout中的onInterceptTouchEvent,然后才是button的dispatchTouchEvent()方法(其中button的事件分发流程就是和上篇View中的分发流程一样)。也就是说,点击一个View事件,首先触发的是父控件的dispatchTouchEvent() -->onInterceptTouchEvent -->然后再传递给子控件进行派发,即子控件的dispatchTouchEvent() .....
由Log1.2 我们可以发现,点击ViewGroup的事件派发和点击View的事件派发有一点差异。差异点主要在在action_down的时候,ViewGroup多了一个onInterceptTouchEvent()方法:
ViewGroup事件顺序为:dispatchTouchEvent->onInterceptTouchEvent->onTouch->onTouchEvent
View事件顺序为:dispatchTouchEvent->onTouch->onTouchEvent
在action_up的时候,LinearLayout却没有触发onInterceptTouchEvent(), 和View的事件派发流程一致。
二。ViewGroup.java传递事件源码分析