先看示例代码
<?xml version="1.0" encoding="utf-8"?>
<com.fy.example.touchevent.view.TouchRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.fy.example.touchevent.view.TouchTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, my TouchEventDemo!" />
</com.fy.example.touchevent.view.TouchRelativeLayout>
两个自定义控件,重写了相关方法,便于考察事件分发
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("MainActivity", "dispatchTouchEvent()");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("MainActivity", "onTouchEvent()");
return super.onTouchEvent(event);
}
}
public class TouchRelativeLayout extends RelativeLayout {
public TouchRelativeLayout(Context context) {
super(context);
}
public TouchRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TouchRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("TouchRelativeLayout", "dispatchTouchEvent()");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d("TouchRelativeLayout", "onInterceptTouchEvent()");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("TouchRelativeLayout", "onTouchEvent()");
return super.onTouchEvent(event);
}
}
public class TouchTextView extends TextView {
public TouchTextView(Context context) {
super(context);
}
public TouchTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TouchTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("TouchTextView", "dispatchTouchEvent()");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("TouchTextView", "onTouchEvent()");
return false;
}
}
点击一下界面中的文本,日志打印如下
12-09 03:13:22.153 1673-1673/com.fy.example.touchevent D/MainActivity: dispatchTouchEvent()
12-09 03:13:22.153 1673-1673/com.fy.example.touchevent D/TouchRelativeLayout: dispatchTouchEvent()
12-09 03:13:22.153 1673-1673/com.fy.example.touchevent D/TouchRelativeLayout: onInterceptTouchEvent()
12-09 03:13:22.153 1673-1673/com.fy.example.touchevent D/TouchTextView: dispatchTouchEvent()
12-09 03:13:22.153 1673-1673/com.fy.example.touchevent D/TouchTextView: onTouchEvent()
12-09 03:13:22.153 1673-1673/com.fy.example.touchevent D/TouchRelativeLayout: onTouchEvent()
12-09 03:13:22.153 1673-1673/com.fy.example.touchevent D/MainActivity: onTouchEvent()
12-09 03:13:22.235 1673-1673/com.fy.example.touchevent D/MainActivity: dispatchTouchEvent()
12-09 03:13:22.235 1673-1673/com.fy.example.touchevent D/MainActivity: onTouchEvent()
12-09 03:13:22.253 1673-1673/com.fy.example.touchevent D/MainActivity: dispatchTouchEvent()
12-09 03:13:22.253 1673-1673/com.fy.example.touchevent D/MainActivity: onTouchEvent()
可见,事件传递过程是由外向内,即事件总是先传递给父元素,然后由父元素分发给子元素。
而由于TextView是不可点击的,它的onTouchEvent默认返回false,这样事件被层层抛上来,最终交给Activity处理。