主要Java方法
-
Android事件分发主要经过3个方法,分别处理事件的分发、拦截、消耗
public boolean dispatchTouchEvent(MotionEvent ev) public boolean onInterceptTouchEvent(MotionEvent ev) public boolean onTouchEvent(MotionEvent event)
-
还有两个与事件处理相关的类
public interface OnTouchListener { boolean onTouch(View var1, MotionEvent var2); } public interface OnClickListener { void onClick(View var1); }
1、如果设置了OnTouchListener,onTouch返回true,表示消耗此事件,那么onTouchEvent方法不再调用
2、如果设置了OnClickListener,onClick是在onTouchEvent方法中被调用的,由此可见它的优先级最低
事件分发规则
事件封装在MotionEvent中,事件最先传递给Activity的dispatchTouchEvent方法进行分发。Activity通过PhoneWindow将事件传递给DecorView,DecorView再传递给ContentView(这个就是我们通过Activity设置的View)。
通过上面的三个控件进行事件分析。这里先假设只有一个ViewGroupA控件,说明一些规则:
- ViewGroupA不处理ACTION_DOWN事件,那么这个事件序列的后续事件不会再传递给ViewGroupA
- ViewGroupA只处理ACTION_DOWN事件,那么这个事件序列的后续事件都会传递给ViewGroupA
- 不处理的事件都会给MainActivity的onTouchEvent处理,也就是说一个事件序列都会有onTouchEvent来消耗(就好比一个事情必须要有人接手,下面的员工不接手,就交给领导接手),Activity的onTouchEvent也返回false只能表示他不想处理,所以是无效的
- onInterceptTouchEvent拦截方法调用的情况:
- ACTION_DOWN事件时会调用,所以这里如果拦截了,也就意味着不会有子View消耗事件,第2种的情况就不会发生
- 有子View消耗事件时且子View未调用requestDisallowInterceptTouchEvent(false)方法要求自己处理事件
有了上面规则的了解,对于事件的分发就很好理解了
几种点击过程分析
-
点击ViewGroupA
打印的日志
===================================DOWN
dispatchTouchEvent Main------>start
dispatchTouchEvent A------>start
onInterceptTouchEvent A------>start
onInterceptTouchEvent A------>false
onTouchEvent A------>start
onTouchEvent A------>true
dispatchTouchEvent A------>true
dispatchTouchEvent Main------>true
===================================MOVE
dispatchTouchEvent Main------>start
dispatchTouchEvent A------>start
onTouchEvent A------>start
onTouchEvent A------>false
dispatchTouchEvent A------>false
onTouchEvent Main------>start
onTouchEvent Main------>false
dispatchTouchEvent Main------>false
===================================UP
dispatchTouchEvent Main------>start
dispatchTouchEvent A------>start
onTouchEvent A------>start
onTouchEvent A------>false
dispatchTouchEvent A------>false
onTouchEvent Main------>start
onTouchEvent Main------>false
dispatchTouchEvent Main------>false -
点击ViewC,不消耗事件
打印的日志
=================================== DOWN
dispatchTouchEvent Main------>start
dispatchTouchEvent A------>start
onInterceptTouchEvent A------>start
onInterceptTouchEvent A------>false
dispatchTouchEvent B------>start
onInterceptTouchEvent B------>start
onInterceptTouchEvent B------>false
dispatchTouchEvent C------>start
onTouchEvent C------>start
onTouchEvent C------>false
dispatchTouchEvent C------>false
onTouchEvent B------>start
onTouchEvent B------>false
dispatchTouchEvent B------>false
onTouchEvent A------>start
onTouchEvent A------>false
dispatchTouchEvent A------>false
onTouchEvent Main------>start
onTouchEvent Main------>false
dispatchTouchEvent Main------>false
=================================== UP
dispatchTouchEvent Main------>start
onTouchEvent Main------>start
onTouchEvent Main------>false
dispatchTouchEvent Main------>false -
点击ViewC处理事件
-
主要的测试源码
public class ViewGroupA extends LinearLayout {public ViewGroupA(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { System.out.println("dispatchTouchEvent A------>start"); boolean b = super.dispatchTouchEvent(ev); System.out.println("dispatchTouchEvent A------>"+b); return b; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { System.out.println("onInterceptTouchEvent A------>start"); boolean b = super.onInterceptTouchEvent(ev); System.out.println("onInterceptTouchEvent A------>"+b); return b; } @Override public boolean onTouchEvent(MotionEvent event) { System.out.println("onTouchEvent A------>start"); boolean b = super.onTouchEvent(event); /*if(event.getAction() == MotionEvent.ACTION_DOWN){ b = true; }*/ System.out.println("onTouchEvent A------>"+b); return b; } }
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) { System.out.println("==================================="); System.out.println("dispatchTouchEvent Main------>start"); boolean b = super.dispatchTouchEvent(ev); System.out.println("dispatchTouchEvent Main------>"+b); return b; } @Override public boolean onTouchEvent(MotionEvent event) { System.out.println("onTouchEvent Main------>start"); boolean b = super.onTouchEvent(event); System.out.println("onTouchEvent Main------>"+b); return b; } }