Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解

来源:互联网 发布:美利坚联盟国 知乎 编辑:程序博客网 时间:2024/05/22 01:37

关于Android的Touch处理过程还是挺复杂的,为了方便后期使用,整理下相关资料如下:

首先触发ACTIVITY的dispatchTouchEvent

然后触发ACTIVITY的onUserInteraction

然后触发LAYOUT的dispatchTouchEvent

然后触发LAYOUT的onInterceptTouchEvent


1.对GroupView中onInterceptTouchEvent方法的理解

onInterceptTouchEvent(MotionEvent ev)方法是GroupView控件中特有的一个方法,我们可以实现这个方法来截获所有的窗口点击事件来根据事件的不同来对子控件或自身分发事件触发。覆盖这个方法时需要小心注意,因为它和View.onTouchEvent(MotionEvent)有着复杂的关系,我们使用是需要和View.onTouchEvent(MotionEvent)一同实现来达到正确的结果,事件触发顺序如下:

  1.你首先会在该方法中得到一个down事件。

  2.这个down事件会被得到处理,要么在这个GroupView中子控件的onTouchEvent()方法中,要么在GroupView自身的onTouchEvent()方法中。当我们在onTouchEvent()方法返回值中返回true的话,将会继续看到后续的触发事件(move、up等),要注意的是当我们在GroupView的onTouchEvent()事件返回值中返回true的话,该方法将不再捕获后续的(move up)事件。

  3.如果在该方法返回值中返回false,down事件将根据控件树结构从根节点向目标子控件的onTouchEvent()方法分发。

  4.如果在该方法返回值中返回true,那么你的子控件将获取不到任何点击事件。

 

  为证明上面所说的顺序特点,下面通过测试代码来观察观察:

public class MainActivity extends Activity {     Group1 group1;     Group2 group2;     MyTextView myTv;      /** Called when the activity is first created. */     @Override     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);                           //--group1         //----|         //-------group2         //---------|         //------------myTv                  group1 = new Group1(this);         group2 = new Group2(this);         myTv = new MyTextView(this);         group2.addView(myTv, new LayoutParams(LayoutParams.FILL_PARENT,                 LayoutParams.FILL_PARENT));         group1.addView(group2, new LayoutParams(LayoutParams.FILL_PARENT,                 LayoutParams.FILL_PARENT));         setContentView(group1);     } }

分别重写Group1和Group2的onInterceptTouchEvent和onTouchEvent方法,重写MyTextView的onTouchEvent方法,最终得到的控件层次结构如下:  

  

  1.在默认返回值情况下logcat输出如下:  

    

  测试后可知默认情况下和所有方法返回值为false的结果一致,down事件的捕获顺序onInterceptTouchEvent先于onTouchEvent,由于onTouchEvent返回值为false,down事件没被消化,后续的move和up事件没有出现,同时逆序返回到父控件的onTouchEvent方法来捕获,如下图所示:  

  

 

  2.所有onTouchEvent返回值为true情况下logcat输出如下:

  

  输出结果可以看出子控件MyTextView消化了down事件,后续的move和up事件正常捕获,由于down事件被消化,上层的onTouchEvent方法不执行,如下图所示:(三箭头分别指down、move、up事件)

  

  既然如此,如果MyTextView中onTouchEvent方法返回为false,而group1和group2的onTouchEvent方法返回true的结果自然也就如下图的顺序了:  

 

  测试输出结果证明了这一猜测顺序,  

    

 

  3.当某个GroupView中的onInterceptTouchEvent方法返回值为true情况下logcat输出如下(如group2):

   

  如果在该方法返回值中返回true,那么子控件将获取不到任何点击事件,转而向自身的onTouchEvent方法转发,如下图所示:

 

  如果onTouchEvent方法返回值都为true,那么根据规律结果就如下图顺序触发:  

   

  最后logcat的结果证实了这一猜测,  

    

2.android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)public boolean dispatchTouchEvent(MotionEvent ev)  这个方法用来分发TouchEvent
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent

当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,然后由  dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。
原创粉丝点击