事件分发机制详解(上)
https://blog.youkuaiyun.com/weixin_37730482/article/details/73810179
本章节通过例子讲述Android的事件分发机制。
一.Activity的事件分发机制
由上述讲解可知,事件分发机制的源头是从Activity开始的,所以先讲解一下Activity的事件分发机制。
Activity代码
package com.wjn.lubandemo.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.wjn.lubandemo.R;
import com.wjn.lubandemo.bean.MyView;
import com.wjn.lubandemo.bean.MyViewGroup;
public class EventActivity extends AppCompatActivity {
private MyViewGroup linearLayout;
private MyView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
ininView();
}
/**
* 初始化各种View
*/
private void ininView() {
textView = findViewById(R.id.activity_event_textview);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "View的onClick点击事件");
}
});
linearLayout = findViewById(R.id.activity_event_linearlayout);
linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "ViewGroup的onClick点击事件!");
}
});
}
/**
* Activity的dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "Activity的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "Activity的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "Activity的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
/**
* Activity的onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "Activity的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "Activity的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "Activity的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
自定义ViewGroup
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyViewGroup extends LinearLayout {
public MyViewGroup(Context context) {
super(context);
}
public MyViewGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
/**
* dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
/**
* onInterceptTouchEvent方法
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的onInterceptTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的onInterceptTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
自定义View
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
public class MyView extends android.support.v7.widget.AppCompatTextView {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
结果
点击View
Activity的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN
View的dispatchTouchEvent方法执行ACTION_DOWN
View的onTouchEvent方法执行ACTION_DOWN
Activity的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的onInterceptTouchEvent方法执行ACTION_MOVE
View的dispatchTouchEvent方法执行ACTION_MOVE
View的onTouchEvent方法执行ACTION_MOVE
...MOVE
Activity的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的onInterceptTouchEvent方法执行ACTION_UP
View的dispatchTouchEvent方法执行ACTION_UP
View的onTouchEvent方法执行ACTION_UP
View的onClick点击事件
点击ViewGroup
Activity的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN
ViewGroup的onTouchEvent方法执行ACTION_DOWN
Activity的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的onTouchEvent方法执行ACTION_MOVE
...MOVE
Activity的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的onTouchEvent方法执行ACTION_UP
ViewGroup的onClick点击事件!
分析
1.当Activity的dispatchTouchEvent方法返回:super.dispatchTouchEvent(ev)。时
<1> 当手指触摸到View时,Activity将事件分发到ViewGroup,然后ViewGroup再将事件分发到View。View的点击事件执行。即事件分发正常。Activity自己的onTouchEvent方法并没有执行。
<2> 当手指触摸到ViewGroup时,Activity将事件分发到ViewGroup。ViewGroup的点击事件执行。即事件分发正常。Activity自己的onTouchEvent方法并没有执行。
2.当Activity的dispatchTouchEvent方法返回:false。时
结果
点击View
Activity的dispatchTouchEvent方法执行ACTION_DOWN
Activity的dispatchTouchEvent方法执行ACTION_MOVE
Activity的dispatchTouchEvent方法执行ACTION_MOVE
Activity的dispatchTouchEvent方法执行ACTION_MOVE
Activity的dispatchTouchEvent方法执行ACTION_UP
点击ViewGroup
Activity的dispatchTouchEvent方法执行ACTION_DOWN
Activity的dispatchTouchEvent方法执行ACTION_MOVE
Activity的dispatchTouchEvent方法执行ACTION_MOVE
Activity的dispatchTouchEvent方法执行ACTION_MOVE
Activity的dispatchTouchEvent方法执行ACTION_UP
<1> 当手指触摸到View时,Activity没有将事件分发到View。Activity自己的onTouchEvent方法并没有执行。
<2> 当手指触摸到ViewGroup时,Activity没有将事件分发到ViewGroup。Activity自己的onTouchEvent方法并没有执行。
3.当Activity的dispatchTouchEvent方法返回:true。
结果
点击View
同 <2>
点击ViewGroup
同 <2>
总结
Activity的dispatchTouchEvent方法返回值
<1> 返回 super.dispatchTouchEvent(ev):事件向下分发传递。
<2> 返回 false:事件将被系统消费,处理。不向下分发传递。
<3> 返回true:事件将被系统消费,处理。不向下分发传递。
至于Activity的onTouchEvent方法一直没有执行,请往下看。
二.ViewGroup的事件分发机制
由上述描述可知,事件分发机制Activity向下分发给ViewGroup。下面我们看一下ViewGroup的事件分发机制。
由于ViewGroup有一个独有的onInterceptTouchEvent方法,所以先看一下这个方法。
1.onInterceptTouchEvent方法
Activity代码
package com.wjn.lubandemo.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.wjn.lubandemo.R;
import com.wjn.lubandemo.bean.MyView;
import com.wjn.lubandemo.bean.MyViewGroup;
public class EventActivity extends AppCompatActivity {
private MyViewGroup linearLayout;
private MyView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
ininView();
}
/**
* 初始化各种View
*/
private void ininView() {
textView = findViewById(R.id.activity_event_textview);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "View的onClick点击事件");
}
});
linearLayout = findViewById(R.id.activity_event_linearlayout);
linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "ViewGroup的onClick点击事件!");
}
});
}
}
ViewGroup代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyViewGroup extends LinearLayout {
public MyViewGroup(Context context) {
super(context);
}
public MyViewGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
/**
* dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
/**
* onInterceptTouchEvent方法
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的onInterceptTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的onInterceptTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
View代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
public class MyView extends android.support.v7.widget.AppCompatTextView {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
结果
点击View
ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN
View的dispatchTouchEvent方法执行ACTION_DOWN
View的onTouchEvent方法执行ACTION_DOWN
ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的onInterceptTouchEvent方法执行ACTION_MOVE
View的dispatchTouchEvent方法执行ACTION_MOVE
View的onTouchEvent方法执行ACTION_MOVE
...MOVE
ViewGroup的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的onInterceptTouchEvent方法执行ACTION_UP
View的dispatchTouchEvent方法执行ACTION_UP
View的onTouchEvent方法执行ACTION_UP
View的onClick点击事件
点击ViewGroup
ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN
ViewGroup的onTouchEvent方法执行ACTION_DOWN
ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的onTouchEvent方法执行ACTION_MOVE
...MOVE
ViewGroup的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的onTouchEvent方法执行ACTION_UP
ViewGroup的onClick点击事件!
分析
1.当ViewGroup的onInterceptTouchEvent方法返回:super.onInterceptTouchEvent(ev)。时
<1> 当手指触摸到View时,ViewGroup将事件分发到View。View的点击事件执行。即事件分发正常。
<2> 当手指触摸到ViewGroup时,ViewGroup的点击事件执行。即事件分发正常。
2.当ViewGroup的onInterceptTouchEvent方法返回:false。时
结果
点击View
同 <1>
点击ViewGroup
同 <1>
3.当ViewGroup的onInterceptTouchEvent方法返回:true。
结果
点击View
ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN
ViewGroup的onTouchEvent方法执行ACTION_DOWN
ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的onTouchEvent方法执行ACTION_MOVE
...MOVE
ViewGroup的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的onTouchEvent方法执行ACTION_UP
ViewGroup的onClick点击事件!
点击ViewGroup
ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
ViewGroup的onInterceptTouchEvent方法执行ACTION_DOWN
ViewGroup的onTouchEvent方法执行ACTION_DOWN
ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
ViewGroup的onTouchEvent方法执行ACTION_MOVE
...MOVE
ViewGroup的dispatchTouchEvent方法执行ACTION_UP
ViewGroup的onTouchEvent方法执行ACTION_UP
ViewGroup的onClick点击事件!
<1> 当手指触摸到View时,完整的执行了ViewGroup的onTouchEvent方法。
<2> 当手指触摸到ViewGroup时,完整的执行了ViewGroup的onTouchEvent方法。
总结
ViewGroup的onInterceptTouchEvent方法返回值
<1> 返回 super.onInterceptTouchEvent(ev):默认 事件不拦截,向下分发传递。由子View的dispatchTouchEvent进行处理。
<2> 返回 false:事件不拦截,向下分发传递。由子View的dispatchTouchEvent进行处理。
<3> 返回true:对事件拦截,交给本层的onTouchEvent进行处理。
2.dispatchTouchEvent方法和onTouchEvent方法
举例
Activity代码
package com.wjn.lubandemo.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.wjn.lubandemo.R;
import com.wjn.lubandemo.bean.MyView;
import com.wjn.lubandemo.bean.MyViewGroup;
public class EventActivity extends AppCompatActivity {
private MyViewGroup linearLayout;
private MyView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
ininView();
}
/**
* 初始化各种View
*/
private void ininView() {
textView = findViewById(R.id.activity_event_textview);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "View的onClick点击事件");
}
});
linearLayout = findViewById(R.id.activity_event_linearlayout);
linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "ViewGroup的onClick点击事件!");
}
});
}
/**
* Activity的onTouchEvent方法
* */
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "Activity的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "Activity的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "Activity的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
ViewGroup代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyViewGroup extends LinearLayout {
public MyViewGroup(Context context) {
super(context);
}
public MyViewGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
/**
* dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
View代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
public class MyView extends android.support.v7.widget.AppCompatTextView {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
结果
点击View
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_UP
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_UP
I/EventActivity: View的onTouchEvent方法执行ACTION_UP
I/EventActivity: View的onClick点击事件
点击ViewGroup
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_UP
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_UP
I/EventActivity: ViewGroup的onClick点击事件!
分析
1.当ViewGroup的dispatchTouchEvent方法返回:super.dispatchTouchEvent(ev)。时
<1> 当手指触摸到View时,ViewGroup将事件分发到View。View的点击事件执行。事件分发正常。
<2> 当手指触摸到ViewGroup时,ViewGroup的点击事件执行。事件分发正常。
2.当ViewGroup的dispatchTouchEvent方法返回:false。时
点击View
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: Activity的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: Activity的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: Activity的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: Activity的onTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: Activity的onTouchEvent方法执行ACTION_UP
点击ViewGroup
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: Activity的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: Activity的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: Activity的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: Activity的onTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: Activity的onTouchEvent方法执行ACTION_UP
<1> 当手指触摸到View时,ViewGroup没有将事件分发到View。只执行了ViewGroup的dispatchTouchEvent方法的ACTION_DOWN动作。而是执行了Activity的onTouchEvent方法。ViewGroup的onTouchEvent方法没有执行。事件分发停止。
<2> 当手指触摸到ViewGroup时,ViewGroup没有将事件分发到View。只执行了ViewGroup的dispatchTouchEvent方法的ACTION_DOWN动作。而是执行了Activity的onTouchEvent方法。ViewGroup的onTouchEvent方法没有执行。事件分发停止。
3.当ViewGroup的dispatchTouchEvent方法返回:true。
点击View
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_UP
点击ViewGroup
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: ViewGroup的dispatchTouchEvent方法执行ACTION_UP
<1> 当手指触摸到View时,ViewGroup没有将事件分发到View。而是执行了ViewGroup的dispatchTouchEvent方法的各种动作。ViewGroup的onTouchEvent方法没有执行。事件分发停止。
<2> 当手指触摸到ViewGroup时,ViewGroup没有将事件分发到View。而是执行了ViewGroup的dispatchTouchEvent方法的各种动作。ViewGroup的onTouchEvent方法没有执行。事件分发停止。
总结
ViewGroup的dispatchTouchEvent方法返回值
<1> 返回 super.dispatchTouchEvent(ev):事件正常分发。由子View的dispatchTouchEvent进行处理。
<2> 返回 false:停止分发,交由上层控件的onTouchEvent方法进行消费,如果本层控件是Activity,则事件将被系统消费,处理。
<3> 返回true:当前ViewGroup的dispatchTouchEvent方法消耗所有事件。
三.View的事件分发机制
从上面对ViewGroup事件分发机制可知,View事件分发机制是从dispatchTouchEvent开始的。
举例
Activity代码
package com.wjn.lubandemo.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.wjn.lubandemo.R;
import com.wjn.lubandemo.bean.MyView;
import com.wjn.lubandemo.bean.MyViewGroup;
public class EventActivity extends AppCompatActivity {
private MyViewGroup linearLayout;
private MyView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
ininView();
}
/**
* 初始化各种View
*/
private void ininView() {
textView = findViewById(R.id.activity_event_textview);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "View的onClick点击事件");
}
});
}
}
ViewGroup代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyViewGroup extends LinearLayout {
public MyViewGroup(Context context) {
super(context);
}
public MyViewGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
View代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
public class MyView extends android.support.v7.widget.AppCompatTextView {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* dispatchTouchEvent方法
*/
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的dispatchTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
点击View
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_UP
I/EventActivity: View的onTouchEvent方法执行ACTION_UP
I/EventActivity: View的onClick点击事件
分析
1.当View的dispatchTouchEvent方法返回:super.dispatchTouchEvent(ev)。时
当手指触摸到View时,事件由dispatchTouchEvent方法传递到onTouchEvent方法。View的点击事件执行。事件分发正常。
2.当View的dispatchTouchEvent方法返回:false。时
点击View
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_MOVE
...MOVE
ViewGroup的onTouchEvent方法执行ACTION_UP
ViewGroup的onClick点击事件!
当手指触摸到View时,事件没有由dispatchTouchEvent方法传递到onTouchEvent方法。而是执行了ViewGroup的onTouchEvent方法。ViewGroup的点击事件执行。事件分发停止。
3.当View的dispatchTouchEvent方法返回:true。时
点击View
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: View的dispatchTouchEvent方法执行ACTION_UP
总结
View的dispatchTouchEvent方法返回值
<1> 返回 super.dispatchTouchEvent(ev):事件正常分发。由View的dispatchTouchEvent方法传递给onTouchEvent方法,点击事件方法...。
<2> 返回 false:停止分发,交由上层控件的onTouchEvent方法进行消费,如果本层控件是Activity,则事件将被系统消费,处理。
<3> 返回true:当前View的dispatchTouchEvent方法消耗所有事件。
下面具体说一下View的onTouchEvent方法
举例
Activity代码
package com.wjn.lubandemo.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.wjn.lubandemo.R;
import com.wjn.lubandemo.bean.MyView;
import com.wjn.lubandemo.bean.MyViewGroup;
public class EventActivity extends AppCompatActivity {
private MyViewGroup linearLayout;
private MyView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
ininView();
}
/**
* 初始化各种View
*/
private void ininView() {
textView = findViewById(R.id.activity_event_textview);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "View的onClick点击事件");
}
});
linearLayout = findViewById(R.id.activity_event_linearlayout);
linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "ViewGroup的onClick点击事件!");
}
});
}
}
ViewGroup代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyViewGroup extends LinearLayout {
public MyViewGroup(Context context) {
super(context);
}
public MyViewGroup(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "ViewGroup的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
View代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
public class MyView extends android.support.v7.widget.AppCompatTextView {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
点击View
I/EventActivity: View的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_UP
I/EventActivity: View的onClick点击事件
分析
1.当View的onTouchEvent方法返回:super.onTouchEvent(event)。时
当手指触摸到View时,onTouchEvent方法执行。View的点击事件执行。
2.当View的onTouchEvent方法返回:false。时
点击View
View的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: ViewGroup的onTouchEvent方法执行ACTION_UP
I/EventActivity: ViewGroup的onClick点击事件!
当手指触摸到View时,View的onTouchEvent方法只执行了DOWN事件,然后就传递给它的父类ViewGroup的onTouchEvent方法执行。并且执行了ViewGroup的点击事件。
3.当View的onTouchEvent方法返回:true。时
点击View
I/EventActivity: View的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_UP
当手指触摸到View时,View的onTouchEvent方法执行了。但是View的点击事件没有执行。
总结
View的onTouchEvent方法返回值
<1> 返回 super.onTouchEvent(event):默认消耗当前onTouchEvent事件,如果View同时设置了点击事件,则点击事件也执行。
<2> 返回 false:不响应事件,不断的传递给上层的onTouchEvent方法处理,直到某个View的onTouchEvent返回true,则认为该事件被消费,如果到最顶层View还是返回false,则该事件不消费,将交由Activity的onTouchEvent处理。
<3> 返回true:表示onTouchEvent处理后消耗了当前事件,如果View同时设置了点击事件,则点击事件不执行。
下面看一下View的onTouchEvent和View的setOnTouchListener监听关系。
Activity代码
package com.wjn.lubandemo.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.wjn.lubandemo.R;
import com.wjn.lubandemo.bean.MyView;
import com.wjn.lubandemo.bean.MyViewGroup;
public class EventActivity extends AppCompatActivity {
private MyView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
ininView();
}
/**
* 初始化各种View
*/
private void ininView() {
textView = findViewById(R.id.activity_event_textview);
//点击事件
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("EventActivity", "View的onClick点击事件");
}
});
//触摸事件
textView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的onTouch监听执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的onTouch监听执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的onTouch监听执行ACTION_UP");
break;
default:
break;
}
return false;
}
});
}
}
View代码
package com.wjn.lubandemo.bean;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
public class MyView extends android.support.v7.widget.AppCompatTextView {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* onTouchEvent方法
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.i("EventActivity", "View的onTouchEvent方法执行ACTION_UP");
break;
default:
break;
}
return super.onTouchEvent(event);
}
}
点击View
I/EventActivity: View的onTouch监听执行ACTION_DOWN
I/EventActivity: View的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: View的onTouch监听执行ACTION_UP
I/EventActivity: View的onTouchEvent方法执行ACTION_UP
I/EventActivity: View的onClick点击事件
分析
1.当View的setOnTouchListener监听事件返回 false 且View的onTouchEvent方法返回:super.onTouchEvent(event)。
当手指触摸到View时,先执行onTouch监听再执行onTouchEvent方法。View的点击事件最后执行。
为什么默认情况下,先执行onTouch监听再执行onTouchEvent方法。
以为onTouch监听是在View的dispatchTouchEvent方法中调用的,而onTouchEvent方法是在具体的View(TextView)的onTouchEvent方法中调用。所以onTouch监听优于onTouchEvent方法先执行。
2.当View的setOnTouchListener监听事件返回 false 且View的onTouchEvent方法返回:false。
点击View
I/EventActivity: View的onTouch监听执行ACTION_DOWN
I/EventActivity: View的onTouchEvent方法执行ACTION_DOWN
只执行了onTouch监听和onTouchEvent方法的ACTION_DOWN事件,View的点击事件也没有执行。
3.当View的setOnTouchListener监听事件返回 false 且View的onTouchEvent方法返回:true。
I/EventActivity: View的onTouch监听执行ACTION_DOWN
I/EventActivity: View的onTouchEvent方法执行ACTION_DOWN
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouchEvent方法执行ACTION_MOVE
...MOVE
I/EventActivity: View的onTouch监听执行ACTION_UP
I/EventActivity: View的onTouchEvent方法执行ACTION_UP
只完全执行了onTouch监听和onTouchEvent方法的事件,View的点击事件却没有执行。
4.当View的setOnTouchListener监听事件返回 true 且View的onTouchEvent方法返回:super.onTouchEvent(event)。
点击View
I/EventActivity: View的onTouch监听执行ACTION_DOWN
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_UP
只执行了onTouch监听没有执行onTouchEvent方法,View的点击事件也没有执行。
5.当View的setOnTouchListener监听事件返回 true 且View的onTouchEvent方法返回:false。
点击View
I/EventActivity: View的onTouch监听执行ACTION_DOWN
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_UP
只执行了onTouch监听没有执行onTouchEvent方法,View的点击事件也没有执行。
6.当View的setOnTouchListener监听事件返回 true 且View的onTouchEvent方法返回:true。
点击View
I/EventActivity: View的onTouch监听执行ACTION_DOWN
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_MOVE
I/EventActivity: View的onTouch监听执行ACTION_UP
只执行了onTouch监听没有执行onTouchEvent方法,View的点击事件也没有执行。
四.View的事件分发机制举例说明
1.listview的setOnItemClickListener和setOnItemLongClickListener
//点击事件
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Log.d("PositionTabActivity", "item点击事件!!!!!!!!!!!!");
}
});
//长按事件
listview.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
Log.d("PositionTabActivity", "item长按事件!!!!!!!!!!!!");
return false;
}
});
可以看到长按事件重写的方法是有返回值的返回值类型 boolean
当长按事件返回false时
点击效果
长按效果
也就是说此条件下长按事件结束后(长按item抬起后)还执行了点击事件。
当长按事件返回true时
点击效果
长按效果
也就是说此条件下长按事件结束后(长按item抬起后)没有执行点击事件。
总结:listview item点击事件和长按事件都有的情况下(比如item点击进入详情页 item长按删除 两者功能不一样所以要写两个)
当长按事件返回false时不仅执行长按监听还执行了点击监听。
当长按事件返回true时只执行长按监听。