ホームページ  >  記事  >  Java  >  Android Touch イベント配信メカニズムを 30 分で理解する

Android Touch イベント配信メカニズムを 30 分で理解する

高洛峰
高洛峰オリジナル
2017-01-16 16:46:051212ブラウズ

Touch イベント配信の主役は ViewGroup と View の 2 人だけです。 Activity の Touch イベントは実際に内部 ViewGroup の Touch イベントを呼び出し、ViewGroup として直接処理できます。

View は ViewGroup 内にあり、ViewGroup は他の ViewGroup 内に存在することもできます。このとき、内部の ViewGroup は View として分析されます。

ViewGroup には、onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent の 3 つの関連イベントがあります。 View に関連するイベントは、dispatchTouchEvent と onTouchEvent の 2 つだけです。

まず、ViewGroup の処理フローを分析します。まず、構造モデルの概念が必要です。ViewGroup と View はツリー構造を形成しており、その下に複数の ViewGroup ノードがあります。各ノードの下に ViewGroup ノードや View ノードなどがあります。図に示すように:

30分钟搞清楚Android Touch事件分发机制

Touchイベント(例えばタッチイベント)がルートノード、つまりActiveのViewGroupに到達すると、配信処理はdispatchTouchEventメソッドを呼び出すことで実装されます。サブビュー (ViewGroup) 。簡単に言うと、ViewGroup はそれに含まれるサブ View を走査し、各 View のdispatchTouchEvent メソッドを呼び出します。サブ View が ViewGroup の場合、その内部 View のdispatchTouchEvent メソッドを呼び出し続けます。ビューグループ。上記例のメッセージ配信順序は、①-②-⑤-⑥-⑦-③-④となります。 dispatchTouchEvent メソッドはイベントの配信のみを行います。戻り値が true の場合、順次配信は中断されます。上記例では、⑤の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 が実際には「配布」作業を実行しているのに対し、View のdispatchTouchEvent メソッドは配布作業を実行しないか、配布するオブジェクト自体がであることがわかります。 、タッチイベントを自分に渡すかどうかを決定し、処理のメソッドはonTouchEventイベントです。実際、サブViewのdispatchTouchEventメソッドで実際に実行されるコードは次のようになります

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

通常の状況では、次のようにする必要があります。通常のビューでは繰り返さないでください。配布ロジックを実行しないため、dispatchTouchEvent メソッドを記述します。 Touch イベントが View に到達したときに行うべきことは、それを onTouchEvent イベントで処理するかどうかです。

では、ViewGroup の onTouchEvent イベントはいつ処理されるのでしょうか? ViewGroup のすべてのサブビューが false を返すと、onTouchEvent イベントが実行されます。 ViewGroup は View を継承するため、実際には View のdispatchTouchEvent メソッドを呼び出して onTouchEvent イベントを実行します。

現在の状況から、すべての onTouchEvent に false を返す限り、すべてのサブコントロールがこの Touch イベントに応答することを保証できるように見えます。ただし、ここでの Touch イベントは Action_Down イベント、つまりタッチを押すイベントに限定されており、Aciton_UP と Action_MOVE は実行されないことに注意する必要があります。実際、完全な Touch イベントは、Down、Up、およびいくつかの Move で構成されている必要があります。ダウン モードは、dispatchTouchEvent を通じて配布されます。配布の目的は、完全な Touch リクエストを処理する必要があるビューを見つけることです。 View または ViewGroup の onTouchEvent イベントが true を返した場合、実際にこのリクエストを処理したいのは View であり、後続の Aciton_UP および Action_MOVE は View によって処理されることを意味します。すべての子ビューの onTouchEvent が false を返すと、この Touch リクエストはルート ViewGroup、つまりアクティビティ自体によって処理されます。

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中是不会执行到的,只有Move和UP才会执行到。
    return mTarget.dispatchTouchEvent(ev);
 
  }

ViewGroup には onInterceptTouchEvent もあります。名前から、これがインターセプト イベントであることがわかります。このインターセプト イベントは 2 つの状況で説明する必要があります:

1. ViewGroup の onInterceptTouchEvent で true を返し、Touch イベントに対して Action が Down である場合、これは ViewGroup のすべての配信操作がインターセプトされることを意味します。この場合、mTarget には Down イベントで値が割り当てられるため、mTarget は常に null になります。 mTarge が null なので、ViewGroup の onTouchEvent イベントが実行されます。この場合、ViewGroup を直接 View として扱うことができます。

2. ViewGroup の onInterceptTouchEvent にいる場合、Action が Down であるすべての Touch イベントは False を返し、そのサブ View がすべて返されれば、Down イベントは正常に配信されます。 false の場合、mTarget は空のままで、効果はありません。サブビューが true を返し、mTarget に値が割り当てられている場合、ViewGroup に Action_Move と Aciton_UP を配布すると、Action_Delete の MotionEvent が mTarget に配布され、同時に mTarget の値がクリアされます。 next Action_Move (前の操作が UP でない場合) は ViewGroup の onTouchEvent によって処理されます。

シナリオ 1 はより頻繁に使用されますが、シナリオ 2 はまだ見つかりません。

最初から最後まで要約すると:

1. Touch イベント配信の主役は ViewGroup と View の 2 人だけです。 ViewGroup には、onInterceptTouchEvent、dispatchTouchEvent、および onTouchEvent という 3 つの関連イベントが含まれています。ビューには、dispatchTouchEvent と onTouchEvent という 2 つの関連イベントが含まれています。このうち、ViewGroupはViewを継承しています。

2. ViewGroup と View はツリー構造を形成し、ルート ノードはアクティビティ内に含まれる ViwGroup です。

3. タッチ イベントは、Action_Down、Action_Move、および Aciton_UP で構成されます。完全なタッチ イベントには、Down と Up が 1 つだけあり、Move は 0 になる可能性があります。

4. Activty が Touch イベントを受信すると、サブビューを走査して Down イベントを配信します。 ViewGroup のトラバーサルは再帰的であるとみなすことができます。配布の目的は、この完全なタッチ イベントを実際に処理するビューを見つけることです。このビューは、onTouchEvent の結果で true を返します。

5. サブビューが true を返すと、Down イベントの配信が停止され、サブビューが ViewGroup に記録されます。後続の Move および Up イベントは、サブビューによって直接処理されます。サブ View は ViewGroup に保存されるため、多層 ViewGroup ノード構造では、上位レベルの ViewGroup は、実際にイベントを処理する View が配置される ViewGroup オブジェクトを保存します。たとえば、ViewGroup0-ViewGroup1 の構造に保存されます。 -TextView、TextView は true を返し、これは ViewGroup1 に保存され、ViewGroup1 も true を返し、ViewGroup0 に保存されます。 Move および UP イベントが発生すると、それらはまず ViewGroup0 から ViewGroup1 に渡され、次に ViewGroup1 から TextView に渡されます。

6. ViewGroup 内のすべてのサブビューが Down イベントをキャプチャしない場合、ViewGroup 自体の onTouch イベントがトリガーされます。トリガーする方法は、親クラス View のdispatchTouchEvent メソッドである super.dispatchTouchEvent 関数を呼び出すことです。すべてのサブビューが処理されない場合、Activity の onTouchEvent メソッドがトリガーされます。

7.onInterceptTouchEvent には 2 つの機能があります: 1. Down イベントの配信をインターセプトします。 2. ターゲット ビューへの Up および Move イベントの配信を停止し、ターゲット ビューが配置されている ViewGroup が Up および Move イベントをキャプチャできるようにします。
補足:

「タッチ イベントは、Action_Down、Action_Move、および Aciton_UP で構成されます。完全なタッチ イベントでは、Down と Up は 1 つだけあり、Move は 0 になる可能性がいくつかあります。」とここで追加します。 UPイベントは実際には0かもしれません。
以上がこの記事の全内容です。Touch イベント配信の仕組みを理解するのに役立つことを願っています。

30 分で理解する Android Touch イベント配信メカニズムに関連するその他の記事については、PHP 中国語 Web サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。