一、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; //消耗此事件 } }