上一篇我们介绍了Android事件分发机制之View篇,相信大家对Android的事件分发有了一定的了解!在讲之前我们要明确两个概念:一个是View,一个是ViewGroup。当然ViewGroup是个容器,它的父类是View,它也包含很多子View和ViewGroup。好了,我们进入本文正题吧!
首先我们提供一个Demo的效果图:
该效果图的界面非常简单,界面中只有一个按钮。
一、layout文件
activity_main.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<cn.ithm.eventdemo.MyLayout
android:id="@+id/mylayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >
<cn.ithm.eventdemo.MyButton
android:id="@+id/mybutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</cn.ithm.eventdemo.MyLayout>
</LinearLayout>
二、主要类文件
1.MyButton.java类
public class MyButton extends Button {
private static final String TAG = "MyButton";
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "MyButton dispatchTouchEvent--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "MyButton dispatchTouchEvent--ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
// return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "MyButton onTouchEvent--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "MyButton onTouchEvent--ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
2.MyLayout.java类
public class MyLayout extends LinearLayout {
private static final String TAG = "MyLayout";
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "MyLayout dispatchTouchEvent--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "MyLayout dispatchTouchEvent--ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "MyLayout onInterceptTouchEvent--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "MyLayout onInterceptTouchEvent--ACTION_UP");
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "MyLayout onTouchEvent--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "MyLayout onTouchEvent--ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
3.MainActivity.java类
public class MainActivity extends Activity {
protected static final String TAG = "MainActivity";
private Button button;
private LinearLayout myLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.mybutton);
myLayout = (LinearLayout) findViewById(R.id.mylayout);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Log.i(TAG, "MyButton onclick");
}
});
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "MyButton setOnTouchListener--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "MyButton setOnTouchListener--ACTION_UP");
break;
default:
break;
}
return false;
}
});
myLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Log.i(TAG, "myLayout onclick");
}
});
myLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "myLayout setOnTouchListener--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "myLayout setOnTouchListener--ACTION_UP");
break;
default:
break;
}
return false;
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "MainActivity dispatchTouchEvent--ACTION_DOWN");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "MainActivity dispatchTouchEvent--ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
// return true;
}
}
三、分析事件分发过程
1、首先我们点击“事件分发”按钮,查看LogCat,其打印结果为:
我们发现它的分发顺序为:Activity的dispatchTouchEvent方法->ViewGroup的dispatchTouchEvent方法->ViewGroup的onInterceptTouchEvent的方法->子View的dispatchTouchEvent方法->子View的onTouch的方法->子View的onTouchEvent的方法,然后是up,这个跟down是相同的。最后是子view的onClick事件。
2.然后我们点击界面空白处,查看LogCat,其打印结果为:
我们发现它的分发顺序为:Activity的dispatchTouchEvent方法->ViewGroup的dispatchTouchEvent方法->ViewGroup的onInterceptTouchEvent的方法->ViewGroup的onTouch的方法->ViewGroup的onTouchEvent的方法,然后是up,这个跟down是相同的。最后是ViewGroup的onClick事件。
四、总结
1、其实ViewGroup的事件分发就是比View的多了一个方法onInterceptTouchEvent,为什么会多这样一个方法呢?主要是因为ViewGroup有子View,而View是没有子view的。
2、同理,ViewGroup的事件分发在某个点被消耗了,它也不会继续往下转发下去。
最后,Android的事件分发就简单粗略的讲完了,相信读者应该有个大致的认识了。