欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

30分鐘搞清楚Android Touch事件分發(fā)機制

 更新時間:2016年03月02日 10:53:49   作者:阿冰的學習日記  
30分鐘搞清楚Android Touch事件分發(fā)機制,Touch事件分發(fā)中只有兩個主角:ViewGroup和View,想要深入學習的朋友可以參考本文

Touch事件分發(fā)中只有兩個主角:ViewGroup和View。Activity的Touch事件事實上是調(diào)用它內(nèi)部的ViewGroup的Touch事件,可以直接當成ViewGroup處理。

View在ViewGroup內(nèi),ViewGroup也可以在其他ViewGroup內(nèi),這時候把內(nèi)部的ViewGroup當成View來分析。

ViewGroup的相關事件有三個:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。View的相關事件只有兩個:dispatchTouchEvent、onTouchEvent。

先分析ViewGroup的處理流程:首先得有個結構模型概念:ViewGroup和View組成了一棵樹形結構,最頂層為Activity的ViewGroup,下面有若干的ViewGroup節(jié)點,每個節(jié)點之下又有若干的ViewGroup節(jié)點或者View節(jié)點,依次類推。如圖:

當一個Touch事件(觸摸事件為例)到達根節(jié)點,即Acitivty的ViewGroup時,它會依次下發(fā),下發(fā)的過程是調(diào)用子View(ViewGroup)的dispatchTouchEvent方法實現(xiàn)的。簡單來說,就是ViewGroup遍歷它包含著的子View,調(diào)用每個View的dispatchTouchEvent方法,而當子View為ViewGroup時,又會通過調(diào)用ViwGroup的dispatchTouchEvent方法繼續(xù)調(diào)用其內(nèi)部的View的dispatchTouchEvent方法。上述例子中的消息下發(fā)順序是這樣的:①-②-⑤-⑥-⑦-③-④。dispatchTouchEvent方法只負責事件的分發(fā),它擁有boolean類型的返回值,當返回為true時,順序下發(fā)會中斷。在上述例子中如果⑤的dispatchTouchEvent返回結果為true,那么⑥-⑦-③-④將都接收不到本次Touch事件。來個簡單版的代碼加深理解:
 

/**
   * ViewGroup
   * @param ev
   * @return
   */
  public boolean dispatchTouchEvent(MotionEvent ev){
    ....//其他處理,在此不管
    View[] views=getChildView();
    for(int i=0;i<views.length;i++){
      //判斷下Touch到屏幕上的點在該子View上面 
      if(...){
      if(views[i].dispatchTouchEvent(ev))
       return true;
       }
    }
    ...//其他處理,在此不管
  }
  /**
   * View
   * @param ev
   * @return
   */
  public boolean dispatchTouchEvent(MotionEvent ev){
    ....//其他處理,在此不管
    return false;
  }

在此可以看出,ViewGroup的dispatchTouchEvent是真正在執(zhí)行“分發(fā)”工作,而View的dispatchTouchEvent方法,并不執(zhí)行分發(fā)工作,或者說它分發(fā)的對象就是自己,決定是否把touch事件交給自己處理,而處理的方法,便是onTouchEvent事件,事實上子View的dispatchTouchEvent方法真正執(zhí)行的代碼是這樣的

/**
   * View
   * @param ev
   * @return
   */
  public boolean dispatchTouchEvent(MotionEvent ev){
    ....//其他處理,在此不管
    return onTouchEvent(event);
  }

一般情況下,我們不該在普通View內(nèi)重寫dispatchTouchEvent方法,因為它并不執(zhí)行分發(fā)邏輯。當Touch事件到達View時,我們該做的就是是否在onTouchEvent事件中處理它。

那么,ViewGroup的onTouchEvent事件是什么時候處理的呢?當ViewGroup所有的子View都返回false時,onTouchEvent事件便會執(zhí)行。由于ViewGroup是繼承于View的,它其實也是通過調(diào)用View的dispatchTouchEvent方法來執(zhí)行onTouchEvent事件。

 

在目前的情況看來,似乎只要我們把所有的onTouchEvent都返回false,就能保證所有的子控件都響應本次Touch事件了。但必須要說明的是,這里的Touch事件,只限于Acition_Down事件,即觸摸按下事件,而Aciton_UP和Action_MOVE卻不會執(zhí)行。事實上,一次完整的Touch事件,應該是由一個Down、一個Up和若干個Move組成的。Down方式通過dispatchTouchEvent分發(fā),分發(fā)的目的是為了找到真正需要處理完整Touch請求的View。當某個View或者ViewGroup的onTouchEvent事件返回true時,便表示它是真正要處理這次請求的View,之后的Aciton_UP和Action_MOVE將由它處理。當所有子View的onTouchEvent都返回false時,這次的Touch請求就由根ViewGroup,即Activity自己處理了。

看看改進后的ViewGroup的dispatchTouchEvent方法

View mTarget=null;//保存捕獲Touch事件處理的View
  public boolean dispatchTouchEvent(MotionEvent ev) {

    //....其他處理,在此不管
    
    if(ev.getAction()==KeyEvent.ACTION_DOWN){
      //每次Down事件,都置為Null

      if(!onInterceptTouchEvent()){
      mTarget=null;
      View[] views=getChildView();
      for(int i=0;i<views.length;i++){
        if(views[i].dispatchTouchEvent(ev))
          mTarget=views[i];
          return true;
      }
     }
    }
    //當子View沒有捕獲down事件時,ViewGroup自身處理。這里處理的Touch事件包含Down、Up和Move
    if(mTarget==null){
      return super.dispatchTouchEvent(ev);
    }
    //...其他處理,在此不管
    if(onInterceptTouchEvent()){
     //...其他處理,在此不管  
     }
//這一步在Action_Down中是不會執(zhí)行到的,只有Move和UP才會執(zhí)行到。
    return mTarget.dispatchTouchEvent(ev);

  }

ViewGroup還有個onInterceptTouchEvent,看名字便知道這是個攔截事件。這個攔截事件需要分兩種情況來說明:

1.假如我們在某個ViewGroup的onInterceptTouchEvent中,將Action為Down的Touch事件返回true,那便表示將該ViewGroup的所有下發(fā)操作攔截掉,這種情況下,mTarget會一直為null,因為mTarget是在Down事件中賦值的。由于mTarge為null,該ViewGroup的onTouchEvent事件被執(zhí)行。這種情況下可以把這個ViewGroup直接當成View來對待。

2.假如我們在某個ViewGroup的onInterceptTouchEvent中,將Acion為Down的Touch事件都返回false,其他的都返回True,這種情況下,Down事件能正常分發(fā),若子View都返回false,那mTarget還是為空,無影響。若某個子View返回了true,mTarget被賦值了,在Action_Move和Aciton_UP分發(fā)到該ViewGroup時,便會給mTarget分發(fā)一個Action_Delete的MotionEvent,同時清空mTarget的值,使得接下去的Action_Move(如果上一個操作不是UP)將由ViewGroup的onTouchEvent處理。

情況一用到的比較多,情況二個人還未找到使用場景。

從頭到尾總結一下:

1.Touch事件分發(fā)中只有兩個主角:ViewGroup和View。ViewGroup包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent三個相關事件。View包含dispatchTouchEvent、onTouchEvent兩個相關事件。其中ViewGroup又繼承于View。

2.ViewGroup和View組成了一個樹狀結構,根節(jié)點為Activity內(nèi)部包含的一個ViwGroup。

3.觸摸事件由Action_Down、Action_Move、Aciton_UP組成,其中一次完整的觸摸事件中,Down和Up都只有一個,Move有若干個,可以為0個。

4.當Acitivty接收到Touch事件時,將遍歷子View進行Down事件的分發(fā)。ViewGroup的遍歷可以看成是遞歸的。分發(fā)的目的是為了找到真正要處理本次完整觸摸事件的View,這個View會在onTouchuEvent結果返回true。

5.當某個子View返回true時,會中止Down事件的分發(fā),同時在ViewGroup中記錄該子View。接下去的Move和Up事件將由該子View直接進行處理。由于子View是保存在ViewGroup中的,多層ViewGroup的節(jié)點結構時,上級ViewGroup保存的會是真實處理事件的View所在的ViewGroup對象:如ViewGroup0-ViewGroup1-TextView的結構中,TextView返回了true,它將被保存在ViewGroup1中,而ViewGroup1也會返回true,被保存在ViewGroup0中。當Move和UP事件來時,會先從ViewGroup0傳遞至ViewGroup1,再由ViewGroup1傳遞至TextView。

6.當ViewGroup中所有子View都不捕獲Down事件時,將觸發(fā)ViewGroup自身的onTouch事件。觸發(fā)的方式是調(diào)用super.dispatchTouchEvent函數(shù),即父類View的dispatchTouchEvent方法。在所有子View都不處理的情況下,觸發(fā)Acitivity的onTouchEvent方法。

7.onInterceptTouchEvent有兩個作用:1.攔截Down事件的分發(fā)。2.中止Up和Move事件向目標View傳遞,使得目標View所在的ViewGroup捕獲Up和Move事件。
 補充:

“觸摸事件由Action_Down、Action_Move、Aciton_UP組成,其中一次完整的觸摸事件中,Down和Up都只有一個,Move有若干個,可以為0個?!?,這里補充下其實UP事件是可能為0個的。
以上就是本文的全部內(nèi)容,希望對大家理解Touch事件分發(fā)機制有所幫助。

相關文章

  • Android實現(xiàn)粒子爆炸效果的方法

    Android實現(xiàn)粒子爆炸效果的方法

    這篇文章主要介紹了Android實現(xiàn)粒子爆炸效果的方法,實例分析了Android動畫特效的實現(xiàn)技巧,需要的朋友可以參考下
    2015-06-06
  • Android實現(xiàn)動態(tài)體溫計

    Android實現(xiàn)動態(tài)體溫計

    這篇文章主要為大家詳細介紹了Android實現(xiàn)動態(tài)體溫計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Android中通過RxJava進行響應式程序設計的入門指南

    Android中通過RxJava進行響應式程序設計的入門指南

    響應式編程在Android中的運用是非常犀利的,比如在異常處理和調(diào)度器方面,這里我們將從生命周期等方面來講解Android中通過RxJava進行響應式程序設計的入門指南:
    2016-06-06
  • Android WebView組件用法詳解

    Android WebView組件用法詳解

    這篇文章主要介紹了Android WebView組件用法,結合實例形式詳細分析了Android WebView組件的功能、權限設置、布局及使用技巧,需要的朋友可以參考下
    2016-02-02
  • Flutter應用程序實現(xiàn)隱私屏幕示例解析

    Flutter應用程序實現(xiàn)隱私屏幕示例解析

    這篇文章主要為大家介紹了Flutter應用程序實現(xiàn)隱私屏幕示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Android?studio實現(xiàn)動態(tài)背景頁面

    Android?studio實現(xiàn)動態(tài)背景頁面

    這篇文章主要為大家詳細介紹了Android?studio實現(xiàn)動態(tài)背景頁面,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Android 連接匿名WiFi的示例代碼

    Android 連接匿名WiFi的示例代碼

    這篇文章主要介紹了Android 連接匿名WiFi的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • Android編程實現(xiàn)上方通知欄里閃動效果的方法

    Android編程實現(xiàn)上方通知欄里閃動效果的方法

    這篇文章主要介紹了Android編程實現(xiàn)上方通知欄里閃動效果的方法,結合實例形式分析了Android通知欄動畫特效具體實現(xiàn)技巧,需要的朋友可以參考下
    2017-02-02
  • Android無障礙監(jiān)聽通知的實戰(zhàn)過程

    Android無障礙監(jiān)聽通知的實戰(zhàn)過程

    開發(fā)微動手勢的時候,做了一個通知觸發(fā)的功能,就是在收到某個預設的通知的時候,自動觸發(fā)某個動作,因此需要監(jiān)聽通知消息,這篇文章主要給大家介紹了關于Android無障礙監(jiān)聽通知的相關資料,需要的朋友可以參考下
    2022-07-07
  • Android編程實現(xiàn)的首頁左右滑動切換功能示例

    Android編程實現(xiàn)的首頁左右滑動切換功能示例

    這篇文章主要介紹了Android編程實現(xiàn)的首頁左右滑動切換功能,涉及Android事件監(jiān)聽及響應相關操作技巧,需要的朋友可以參考下
    2017-07-07

最新評論