<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ***** **事件分發流程** [TOC=6] # 1. 事件分發機制方法&流程介紹 ## 先搞明白Activity的dispatchTouchEvent() [參考博客](https://blog.csdn.net/hzmming2008/article/details/82347416) ## 1.1 事件分發機制方法 事件分發過程由dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()三個方法協助完成,如下圖: ![](http://upload-images.jianshu.io/upload_images/944365-74bdb5c375a37100.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 方法詳細介紹 * Android事件分發流程如下:(**必須熟記**) > Android事件分發順序:**Activity(Window) -> ViewGroup -> View** ![](http://upload-images.jianshu.io/upload_images/944365-aa8416fc6d2e5ecd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 事件分發機制詳細流程 其中: * super:調用父類方法 * true:消費事件,即事件不繼續往下傳遞 * false:不消費事件,事件也不繼續往下傳遞 / 交由給父控件onTouchEvent()處理 **接下來,我將詳細介紹這3個方法及相關流程。** ## 1.2 dispatchTouchEvent() | 屬性 | 介紹 | | --- | --- | | 使用對象 | Activity、ViewGroup、View | | 作用 | 分發點擊事件 | | 調用時刻 | 當點擊事件能夠傳遞給當前View時,該方法就會被調用 | | 返回結果 | 是否消費當前事件,詳細情況如下: | **1\. 默認情況:根據當前對象的不同而返回方法不同** | 對象 | 返回方法 | 備注 | | --- | --- | --- | | Activity | super.dispatchTouchEvent() | 即調用父類ViewGroup的dispatchTouchEvent() | | ViewGroup | onIntercepTouchEvent() | 即調用自身的onIntercepTouchEvent() | | View | onTouchEvent() | 即調用自身的onTouchEvent() | ![](http://upload-images.jianshu.io/upload_images/944365-673eacf259c8b50c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程解析 **2\. 返回true** * 消費事件 * 事件不會往下傳遞 * 后續事件(Move、Up)會繼續分發到該View * 流程圖如下: ![](http://upload-images.jianshu.io/upload_images/944365-919f10d7d671cdea.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 **3\. 返回false** * 不消費事件 * 事件不會往下傳遞 * 將事件回傳給父控件的onTouchEvent()處理 > Activity例外:返回false=消費事件 * 后續事件(Move、Up)會繼續分發到該View(與onTouchEvent()區別) * 流程圖如下: ![](http://upload-images.jianshu.io/upload_images/944365-8b45e9551e833955.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 ## 1.3 onTouchEvent() | 屬性 | 介紹 | | --- | --- | | 使用對象 | Activity、ViewGroup、View | | 作用 | 處理點擊事件 | | 調用時刻 | 在dispatchTouchEvent()內部調用 | | 返回結果 | 是否消費(處理)當前事件,詳細情況如下: | > 與dispatchTouchEvent()類似 **1\. 返回true** * 自己處理(消費)該事情 * 事件停止傳遞 * 該事件序列的后續事件(Move、Up)讓其處理; * 流程圖如下: ![](http://upload-images.jianshu.io/upload_images/944365-cd63e2c3b7f89b47.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 **2\. 返回false(同默認實現:調用父類onTouchEvent())** * 不處理(消費)該事件 * 事件往上傳遞給父控件的onTouchEvent()處理 * 當前View不再接受此事件列的其他事件(Move、Up); * 流程圖如下: ![](http://upload-images.jianshu.io/upload_images/944365-9ce60722ac0a9a36.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 ## 1.4 onInterceptTouchEvent() | 屬性 | 介紹 | | --- | --- | | 使用對象 | ViewGroup(注:Activity、View都沒該方法) | | 作用 | 攔截事件,即自己處理該事件 | | 調用時刻 | 在ViewGroup的dispatchTouchEvent()內部調用 | | 返回結果 | 是否攔截當前事件,詳細情況如下: | ![](http://upload-images.jianshu.io/upload_images/944365-6b34c1017b14104d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 返回結果 * 流程圖如下: ![](http://upload-images.jianshu.io/upload_images/944365-37be4474ef7a1741.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 ## 1.5 三者關系 下面將用一段偽代碼來闡述上述三個方法的關系和點擊事件傳遞規則 ~~~ public boolean dispatchTouchEvent(MotionEvent ev) { //代表是否消耗事件 boolean consume = false; if (onInterceptTouchEvent(ev)) { //如果onInterceptTouchEvent()返回true則代表當前View攔截了點擊事件 //則該點擊事件則會交給當前View進行處理 //即調用onTouchEvent ()方法去處理點擊事件 consume = onTouchEvent(ev); } else { //如果onInterceptTouchEvent()返回false則代表當前View不攔截點擊事件 //則該點擊事件則會繼續傳遞給它的子元素 //子元素的dispatchTouchEvent()就會被調用,重復上述過程 //直到點擊事件被最終處理為止 consume = child.dispatchTouchEvent(ev); } return consume; } ~~~ ## 1.5 總結 * 對于事件分發的3個方法,你了解嗎? # 2. 幾個重要的事件 DOWN、MOVE、UP、CANCEL # 3\. 事件分發場景介紹 下面我將利用例子來說明常見的點擊事件傳遞情況 ### 3.1 背景描述 我們將要討論的布局層次如下: ![](http://upload-images.jianshu.io/upload_images/944365-ecac6247816a3db1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 布局層次 * 最外層:Activiy A,包含兩個子View:ViewGroup B、View C * 中間層:ViewGroup B,包含一個子View:View C * 最內層:View C 假設用戶首先觸摸到屏幕上View C上的某個點(如圖中黃色區域),那么Action\_DOWN事件就在該點產生,然后用戶移動手指并最后離開屏幕。 ### 3.2 一般的事件傳遞情況 一般的事件傳遞場景有: * 默認情況 * 處理事件 * 攔截DOWN事件 * 攔截后續事件(MOVE、UP) ### 3.2.1 默認情況 * 即不對控件里的方法(dispatchTouchEvent()、onTouchEvent()、onInterceptTouchEvent())進行重寫或更改返回值 * 那么調用的是這3個方法的默認實現:調用父類的方法 * 事件傳遞情況:(如圖下所示) * 從Activity A---->ViewGroup B--->View C,從上往下調用dispatchTouchEvent() * 再由View C--->ViewGroup B --->Activity A,從下往上調用onTouchEvent() ![](http://upload-images.jianshu.io/upload_images/944365-69229fd4a804c0f8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 注:雖然ViewGroup B的onInterceptTouchEvent方法對DOWN事件返回了false,后續的事件(MOVE、UP)依然會傳遞給它的onInterceptTouchEvent() > 這一點與onTouchEvent的行為是不一樣的。 #### 3.2.2 處理事件 假設View C希望處理這個點擊事件,即C被設置成可點擊的(Clickable)或者覆寫了C的onTouchEvent方法返回true。 > 最常見的:設置Button按鈕來響應點擊事件 事件傳遞情況:(如下圖) * DOWN事件被傳遞給C的onTouchEvent方法,該方法返回true,表示處理這個事件 * 因為C正在處理這個事件,那么DOWN事件將不再往上傳遞給B和A的onTouchEvent(); * 該事件列的其他事件(Move、Up)也將傳遞給C的onTouchEvent() ![](http://upload-images.jianshu.io/upload_images/944365-26290b0d33370853.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 #### 3.2.3 攔截DOWN事件 假設ViewGroup B希望處理這個點擊事件,即B覆寫了onInterceptTouchEvent()返回true、onTouchEvent()返回true。 事件傳遞情況:(如下圖) * DOWN事件被傳遞給B的onInterceptTouchEvent()方法,該方法返回true,表示攔截這個事件,即自己處理這個事件(不再往下傳遞) * 調用onTouchEvent()處理事件(DOWN事件將不再往上傳遞給A的onTouchEvent()) * 該事件列的其他事件(Move、Up)將直接傳遞給B的onTouchEvent() > 該事件列的其他事件(Move、Up)將不會再傳遞給B的onInterceptTouchEvent方法,該方法一旦返回一次true,就再也不會被調用了。 ![](http://upload-images.jianshu.io/upload_images/944365-d8acd35d3a50e091.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 #### 3.2.4 攔截DOWN的后續事件 假設ViewGroup B沒有攔截DOWN事件(還是View C來處理DOWN事件),但它攔截了接下來的MOVE事件。 * DOWN事件傳遞到C的onTouchEvent方法,返回了true。 * 在后續到來的MOVE事件,B的onInterceptTouchEvent方法返回true攔截該MOVE事件,但該事件并沒有傳遞給B;這個MOVE事件將會被系統變成一個CANCEL事件傳遞給C的onTouchEvent方法 * 后續又來了一個MOVE事件,該MOVE事件才會直接傳遞給B的onTouchEvent() > 1. 后續事件將直接傳遞給B的onTouchEvent()處理 > 2. 后續事件將不會再傳遞給B的onInterceptTouchEvent方法,該方法一旦返回一次true,就再也不會被調用了。 * C再也不會收到該事件列產生的后續事件。 ![](http://upload-images.jianshu.io/upload_images/944365-edb138a07cbb990c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 流程圖 特別注意: * 如果ViewGroup A 攔截了一個半路的事件(如MOVE),這個事件將會被系統變成一個CANCEL事件并傳遞給之前處理該事件的子View; * 該事件不會再傳遞給ViewGroup A的onTouchEvent() * 只有再到來的事件才會傳遞到ViewGroup A的onTouchEvent() ### 3.3 總結 * 對于Android的事件分發機制,你應該已經非常清楚了
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看