前一階段,在學習的時候,遇到了我覺得的我接觸安卓以來的最多的一次事件攔截出來,那個項目,用到了slidemenu側滑菜單條,然后加上tab標簽,還有輪播廣告,listview上下滑動。viewpager的左右監聽,假設沒有處理各種事件的監聽,那么就會一團糟。會讓系統不知道究竟要響應你的哪一個事件,有了點啟示。在這自己就寫一個小的demo來分享一下事件的攔截機制。
我們想要了解事件攔截機制,我們首先來看下onInterceptTouchEvent這種方法:
onInterceptTouchEvent:
- 負責對touch事件攔截。對於嵌套的view。最先運行的是所點擊view的onInterceptTouchEvent,然后依次運行子視圖中的onInterceptTouchEvent(這里沒有做不論什么處理。假設全部嵌套視圖的onInterceptTouchEvent都會得到運行。也就是默認的返回false)就是有事情了,總監先去處理,然后經理處理。然后員工處理。(父視圖先處理事情),事件攔截成功的標志就是onInterceptTouchEvent的返回值。假設返回fasle,沒有攔截成功,返回true,攔截成功。
首先來看下我的文件布局:(最上面是一個自己定義的view,中間的和以下的是兩個自己定義的viewgroup)
布局非常easy:中間的和以下的那個是繼承的RelativeLayout,最上面的繼承的textview。
package com.example.touchintercept;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
/** * Created by 若蘭 on 2016/2/14. * 一個懂得了編程樂趣的小白。希望自己 * 能夠在這個道路上走的非常遠,也希望自己學習到的 * 知識能夠幫助很多其它的人,分享就是學習的一種樂趣 * QQ:1069584784 * csdn:http://blog.csdn.net/wuyinlei */
public class DirectorView extends RelativeLayout {
private static String TAG = "wuyinlei";
public DirectorView(Context context) {
super(context);
}
public DirectorView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public DirectorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d(TAG, "DirectorView onInterceptTouchEvent");
return false;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d(TAG, "DirectorView dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "DirectorView onTouchEvent");
return super.onTouchEvent(event);
}
}
其它的兩個也是一樣的,里面沒有實現不論什么的邏輯。
我們首先來看下,什么處理都沒有做的(僅僅是簡單的寫了onInterceptTouchEvent和onTouchEvent)
這個時候我們來點擊textview。看看打印的log:
能夠看見,正常的狀況事件的傳遞順序是:
- 總監(DirectorView)–>經理(ManagerView)—>我(MyView)
- 事件傳遞的時候。先運行dispatchTouchEvent方法然后運行onInterecptTouchEvent方法
事件處理的順序是:
- 我(MyView)–>經理(ManagerView)—>總監(DirectorView)
- 這個就非常好理解了。比方說賣房的時候,假設買房的要的優惠在員工(我)的能力范圍之內,那么我返回ture,把事件處理了,也就是攔截。假設超出了我的優惠范圍,我就返回false。不攔截。繼續到經理。一層一層的處理。
- 初始情況都是返回false (dispatchTouchEvent方法我們一般不住處理的)
我們來看下整個事件過程的圖形說明:
總監處理事件
以下我們修改一下,假如一個買房的顧客和總監非常熟。那么他直接去找了總監。那么總監直接把優惠給了這個顧客。也就是事件不是必需往下傳遞了,這個時候我們僅僅須要修改DirectorView中的onInterecptTouchEvent方法返回true。我們看下log:
這個時候我們看下圖形解釋的攔截事件:
經理處理事件
在來看下一個場景,這個中產階級的員工,去買房。他僅僅認識經理,那么他直接去找經理談能給的優惠,而且兩個人是好朋友,這個時候就會把他能給的最大優惠給這個買房的。這個時候我們調整ManagerView中的onInterecptTouchEvent方法返回true,我們看下log:
這個時候我們看下圖形解釋的攔截事件:
員工(我)處理事件
這個時候,想必對於事件的分發、攔截大家應該比較清楚了,這個時候我們再來看下底層的MyView.記得我們剛開始的時候,順其自然,我們返回的是false。就是一級一級的往上報告。只是這個時候,過來了一個買房的,有錢,可是不認識經理和總監。當然了哈,他也不在乎錢,這個時候你就給了他自己能給的優惠,兩方達成一致,有錢人買了一套房,你也不用向上級反映。這個時候我們返回true:
這個時候他們之間的關系圖例如以下所看到的:
還有就是。假設經理在onTouchEvent中返回了true。那么事件傳遞到經理這里也就不傳遞了。就好比,員工做錯了事情,經理一看。不想把自己員工丟人的事情讓總監看。那么他就返回true:
這個時候他們之間的關系圖例如以下所看到的:
相信通過這幾步的分析,還是比較easy的了解事件的分發、攔截、處理機制的,假設想要進一步的了解,大家能夠去結合一下源代碼,然后在自己寫一個demo演示,相信會有更深層的體會。