前言
在上一篇文章【【朝花夕拾】Android自定义View篇之(五)Android事件分发机制(上)Touch三个重要方法的处理逻辑】中,我们通过示例和log来分析了Android的事件分发机制。这些,我们只是看到了现象,如果要进一步了解事件分发机制,这是不够的,我们还需要透过现象看本质,去研究研究源码。本文将从源码(基于Android API-26)出发,去分析我们上一篇文章中看到的现象,以及其它一些和事件相关的常见问题,如requestDisallowInterceptTouchEvent为什么失效?view设置了focusable=“false”,为什么还能触发点击事件?Touch事件和Click事件谁先谁后?等等!
一、Activity对事件的处理逻辑
在上一篇文章的代码示例中,我们的Boss——EventDemoActivity类中有如下代码
1 //=============Boss:EventDemoActivity.java============ 2 @Override 3 public boolean dispatchTouchEvent(MotionEvent ev) { 4 Log.i("songzheweiwang", "[EventDemoActivity-->dispatchTouchEvent]ev=" + EventUtil.parseAction(ev.getAction())); 5 return super.dispatchTouchEvent(ev); 6 } 7 8 @Override 9 public boolean onTouchEvent(MotionEvent event) { 10 Log.i("songzheweiwang", "[EventDemoActivity-->onTouchEvent]event=" + EventUtil.parseAction(event.getAction())); 11 return super.onTouchEvent(event); 12 }
Activity是事件的起点,dispatchTouchEvent又是整个逻辑中最早分发事件的地方。但是Activity并不是View体系中的一员,那它是怎样把事件分发到View体系中的呢?追踪super.dispatchTouchEvent方法,会进入到Activity.java中的方法
//==========================Activity.java=======================
1 /** 2 * Called to process touch screen events. You can override this to 3 * intercept all touch screen events before they are dispatched to the 4 * window. Be sure to call this implementation for touch screen events 5 * that should be handled normally. 6 * 7 * @param ev The touch screen event. 8 * 9 * @return boolean Return true if this event was consumed. 10 */ 11 public boolean dispatchTouchEvent(MotionEvent ev) { 12 if (ev.getAction() == MotionEvent.ACTION_DOWN) { 13 onUserInteraction(); 14 } 15 if (getWindow().superDispatchTouchEvent(ev)) { 16 return true; 17 } 18 return onTouchEvent(ev); 19 }
1 //=============Activity.java========== 2 ...... 3 private Window mWindow; 4 ...... 5 public Window getWindow() { 6 return mWindow; 7 } 8 ...... 9 10 //================Window.java================ 11 /** 12 * ...... 13 * <p>The only existing implementation of this abstract class is 14 * android.view.PhoneWindow, which you should instantiate when needing a 15 * Window. 16 */ 17 public abstract class Window { 18 ...... 19 public abstract boolean superDispatchTouchEvent(MotionEvent event); 20 ...... 21 }
1 //=============PhoneWindow.java========== 2 ...... 3 // This is the top-level view of the window, containing the window decor. 4 private DecorView mDecor; 5 ...... 6 @Override 7 public boolean superDispatchTouchEvent(MotionEvent event) { 8 return mDecor.superDispatchTouchEvent(event); 9 } 10 11 //===========DecorView.java========== 12 ...... 13 public boolean superDispatchTouchEvent(MotionEvent event) { 14 return super.dispatchTouchEvent(event); 15 } 16 .... 17 18 //========ViewGroup.java======= 19 @Override 20 public boolean dispatchTouchEvent(MotionEvent ev) { 21 ...... 22 }