最近在作高德地圖的時候,因爲用戶的要求,不得不用ScrollVew嵌套MapView,雖然很官方要求不建議這樣作,但也迫於無奈... 魔高一尺,道高一丈.有什麼事是程序員不能解決的,若是有那就是解決兩次.html
鑑於用到了觸摸事件,因而就來總結了Android的觸摸事件機制.android
首先當用戶進行屏幕操做的時候,則有兩種狀況程序員
一是按鍵事件bash
二是觸摸事件微信
按鍵事件分爲長按和點擊事件,過於簡單,這裏再也不進行總結.ide
觸摸事件的組成:函數
下面介紹一個講的好的一個博客地址:學習
全部Touch事件都被封裝成了MotionEvent對象,包括Touch的位置、時間、歷史記錄以及第幾個手指(多指觸摸)等。spa
分發(不少人也稱做爲傳遞事件) : dispatchTouchEvent函數
消費: onTouchEvent函數和OnTouchListener函數
攔截:onInterceptTouchEvent函數
咱們都知道Android的觸摸事件都是從外層傳遞到內層:由最外層的Activity——>ViewGroup——> ViewGroupo——>.......View.
第一觸摸事件傳遞的開始必定是Activity;
第二傳遞方式是經過隧道方式傳遞;
第三一直傳遞到一個最外層的View,也就是頂級View,由該View的這個方法來進行分發。
對於Activity來講:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isFlag = super.dispatchTouchEvent(ev);
return isFlag;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean isFlag = super.onTouchEvent(event);
return isFlag;
}複製代碼
對於ViewGroup來講:
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean isFlag =super.onTouchEvent(event);
return isFlag;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean isFlag =super.onInterceptTouchEvent(event);
return isFlag;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
boolean isFlag =super.dispatchTouchEvent(event);
return isFlag;
}複製代碼
對於View來講和Activity同樣,只有消費和攔截
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isFlag = super.dispatchTouchEvent(ev);
return isFlag;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean isFlag = super.onTouchEvent(event);
return isFlag;
}複製代碼
www.open-open.com/lib/view/op…
android中的Touch事件都是從ACTION_DOWN開始的:
單手指操做:ACTION_DOWN---ACTION_MOVE----ACTION_UP
多手指操做:ACTION_DOWN---ACTION_POINTER_DOWN---ACTION_MOVE--ACTION_POINTER_UP---ACTION_UP.
若是都不進行攔截,都不消費的基本流程圖:
下面咱們就用案例進行分析:
activity----》ViewGroup(MyLinearLayout)---》ViewGroup(MySubView)
打印結果:
- 過程及結果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分發給 TouchEventFather 控件的dispatchTouchEvent;
而該TouchEventFather 控件的 dispatchTouchEvent 返回 false,表示對獲取到的事件中止向下傳遞,同時也不對該事件進行消費;
因爲 TouchEventFather 獲取的事件直接來自 TouchEventActivity ,則會將事件返回給 TouchEventActivity 的 onTouchEvent 進行消費;
最後直接由 TouchEventActivity 來響應手指移動和擡起事件。
打印結果:
- 過程及結果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分發給 TouchEventFather 控件的 dispatchTouchEvent;
而該TouchEventFather 控件的 dispatchTouchEvent 返回 true,表示分發事件到 TouchEventFather 控件並由該控件的 dispatchTouchEvent 進行消費;
又由於TouchEventActivity 不斷的分發事件到 TouchEventFather 控件的 dispatchTouchEvent,而 TouchEventFather 控件的 dispatchTouchEvent 也不斷的將獲取到的事件進行消費。
打印結果:
過程及結果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分發給 TouchEventFather 控件的 dispatchTouchEvent;
而該TouchEventFather 控件的 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev),表示對事件進行分發並向下傳遞給 TouchEventFather 控件的 onInterceptTouchEvent 方法;
而該方法返回 true 表示對所獲取到的事件進行攔截並將事件傳遞給 TouchEventFather 控件的 onTouchEvent 進行處理,TouchEventFather 控件的 onTouchEvent 返回 super.onTouchEvent(ev) 表示對事件沒有作任何處理直接將事件返回給上級控件;
因爲 TouchEventFather 獲取的事件直接來自 TouchEventActivity,因此 TouchEventFather 控件的 onTouchEvent 會將事件以冒泡方式直接返回給 TouchEventActivity 的 onTouchEvent 進行消費;
後續的事件則會跳過 TouchEventFather 直接由 TouchEventActivity 的 onTouchEvent 消費來自 TouchEventActivity 自身分發的事件。
打印結果:
過程及結果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分發給 TouchEventFather 控件的 dispatchTouchEvent;
而該控件的 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev),表示對事件進行分發並向下傳遞給 TouchEventFather 控件的 onInterceptTouchEvent 方法;
該方法返回 false 表示事件會被放行並傳遞到子控件 TouchEventChilds 的 dispatchTouchEvent 方法;
一樣 TouchEventChilds 的 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev),表示對事件進行分發並向下傳遞給 TouchEventChilds 控件的 onInterceptTouchEvent 方法;
而TouchEventChilds 的 onInterceptTouchEvent 方法返回 super.onInterceptTouchEvent(ev) ,默認會將事件傳遞給 TouchEventChilds 的 onTouchEvent 進行處理;
而TouchEventChilds 的 onTouchEvent 返回 super.onTouchEvent(ev) 表示對事件沒有作任何處理直接將事件返回給上級控件;
因爲 TouchEventChilds 獲取的事件直接來自 TouchEventFather,因此 TouchEventChilds 控件的 onTouchEvent 會將事件以冒泡方式直接返回給 TouchEventFather 的 onTouchEvent 進行消費;
而 TouchEventFather 的 onTouchEvent 也返回了 super.onTouchEvent(ev),一樣 TouchEventFather 的 onTouchEvent 也會將事件返回給上級控件;
而 TouchEventFather 獲取的事件直接來自 TouchEventActivity,因此 TouchEventFather 控件的 onTouchEvent 會將事件以冒泡方式直接返回給 TouchEventActivity 的 onTouchEvent 進行消費;
後續的事件則會跳過 TouchEventFather 和 TouchEventChilds 直接由 TouchEventActivity 的 onTouchEvent 消費來自 TouchEventActivity 自身分發的事件。
打印結果:
過程及結果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分發給 TouchEventFather 控件的 dispatchTouchEvent;
該控件的 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev),事件會分發到 TouchEventFather 的 onInterceptTouchEvent,此方法返回 false 表示放行當先事件;
事件會被傳遞到子控件 TouchEventChilds 的 dispatchTouchEvent 方法,dispatchTouchEvent 返回 true 表示事件被分發到 TouchEventChilds ,並由 dispatchTouchEvent 方法消費;
後續的事件也會不斷的重複上面的邏輯最終被 TouchEventChilds 的 dispatchTouchEvent 消費。
down事件首先會傳遞到onInterceptTouchEvent()方法
若是該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成以後return false,內部view將也會獲取到down,那麼後續的move, up等事件將繼續會先傳遞給該ViewGroup,以後同樣傳遞給最終的目標view的onTouchEvent()處理。
若是該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成以後return true,內部view不會貨到down,後續的move, up等事件也再也不傳遞給onInterceptTouchEvent(),固然,move,up也不會傳給view
若是最終須要處理事件的view的onTouchEvent()返回了false,那麼該事件將被傳遞至其上一層次的view的onTouchEvent()處理。
若是最終須要處理事件的view 的onTouchEvent()返回了true,那麼後續事件將能夠繼續傳遞給該view的onTouchEvent()處理。
group的touch和這個機制不要緊,與上一級有關係。
來自androidstarjack博客地址:
若是你以爲此文對您有所幫助,歡迎入羣 QQ交流羣 :232203809
微信公衆號:終端研發部
(歡迎關注學習和交流)