一、android 事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。android
二、在ViewGroup中能够经过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true表明不容许事件继续向子View传递, 返回false表明不对事件拦截。ide
三、子View中若是将传递的事件消费掉,ViewGroup将没法接收到任何事件。spa
四、super.onInterceptTouchEvent(ev)默认为FALSE3d
五、事件传递机制的步骤:rest
5.一、view执行dispatchTouchEvent方法,开始分发事件code
5.二、执行onInterceptTouchEvent判断是否中断事件分发blog
4.三、执行onTouchEvent方法,去处理事件事件
六、touch事件处理流程图get
七、多点触控事件it
在android的中,MotionEvent event表明的是一个触摸事件。咱们对屏幕的几乎全部操做都会触发该事件,如点击、放开、滑动等。不一样的事件在MotionEvent中有不一样的id,根据id的不一样能够判断触摸事件属于哪一个手指。
在MotionEvent类中有两个参数能够用来获取对触摸的控制,这两个参数分别为:MotionEvent.getAction()和MotionEvent.ACTION_MASK,前者用于对单点触控进行操做,后者用于对多点触控进行操做,相应地,咱们能够经过Android Developers’ Reference看到,对于单点触控,咱们由MotionEvent.getAction()能够获得如下几种事件:ACTION_DOWN、ACTION_UP,而对于多点触控,由MotionEvent.ACTION_MASK,咱们能够获得:ACTION_POINTER_DOWN、ACTION_POINTER_UP,都是MotionEvent中的常量,能够直接调用。而有些常量则是单点和多点共用的,如:ACTION_MOVE,所以在按下时,咱们必须标记单点与多点触控的区别。
下面将介绍一下上面提到的五个操做:
举例来说:当咱们放一个食指到屏幕上时,触发ACTION_DOWN事件;再放一个拇指到屏幕上,触发ACTION_POINTER_DOWN事件;此时再把食指或拇指放开,都会触发ACTION_POINTER_UP事件;再放开最后一个手指,触发ACTION_UP事件;而同时在整个过程当中,ACTION_MOVE事件会一直不停地被触发。例子代码以下所示:
/** * 多指操做时,为了不多个事件进行响应,当多个点被按住时,阻止事件向下分发 * * */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub switch (ev.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: //在第一个点被按下时触发 case MotionEvent.ACTION_UP: //当屏幕上惟一的点被放开时触发 case MotionEvent.ACTION_POINTER_UP: //当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)。 break; case MotionEvent.ACTION_POINTER_DOWN: //当屏幕上已经有一个点被按住,此时再按下其余点时触发。 return true; //中断事件向下分发 } return false; //触摸事件继续向下分发 }
八、一个自定义的LinearLayout的代码
package com.example.pinterestlistview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; public class MyLinearLayout extends LinearLayout { public MyLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; //中断事件向下分发 } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("fuyanan", "yanan:"+super.dispatchTouchEvent(ev)); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { int width=getWidth()/getChildCount(); int height = getHeight(); int count=getChildCount(); Log.i("fuyanan", "yanan:"+count); float eventX = event.getX(); if (eventX<width){ // 滑动左边的 listView event.setLocation(width/2, event.getY()); Log.i("fuyanan", "yanan:"+getChildAt(0)); getChildAt(0).dispatchTouchEvent(event); // 事件分发给第一个孩子 return true; } else if (eventX > width && eventX < 2 * width) { //滑动中间的 listView float eventY = event.getY(); if (eventY < height / 2) { event.setLocation(width / 2, event.getY()); for (int i = 0; i < count; i++) { View child = getChildAt(i); try { child.dispatchTouchEvent(event); 事件分发给全部的孩子 } catch (Exception e) { e.printStackTrace(); } } return true; } else if (eventY > height / 2) { event.setLocation(width / 2, event.getY()); try { getChildAt(1).dispatchTouchEvent(event); } catch (Exception e) { e.printStackTrace(); } return true; } }else if (eventX>2*width){ event.setLocation(width/2, event.getY()); getChildAt(2).dispatchTouchEvent(event); 事件分发给第三个孩子 return true; } return true; //消耗此事件 } }