Heim  >  Artikel  >  Java  >  Verstehen Sie den Android Touch-Ereignisverteilungsmechanismus in 30 Minuten

Verstehen Sie den Android Touch-Ereignisverteilungsmechanismus in 30 Minuten

高洛峰
高洛峰Original
2017-01-16 16:46:051212Durchsuche

Es gibt nur zwei Protagonisten bei der Touch-Ereignisverteilung: ViewGroup und View. Das Touch-Ereignis der Aktivität ruft tatsächlich das Touch-Ereignis seiner internen ViewGroup auf und kann direkt als ViewGroup verarbeitet werden.

Ansicht befindet sich in einer ViewGroup, und eine ViewGroup kann sich auch in einer anderen ViewGroup befinden. Zu diesem Zeitpunkt wird die interne ViewGroup als Ansicht analysiert.

ViewGroup verfügt über drei verwandte Ereignisse: onInterceptTouchEvent, DispatchTouchEvent und onTouchEvent. Für View gibt es nur zwei verwandte Ereignisse: „dispatchTouchEvent“ und „onTouchEvent“.

Analysieren Sie zunächst den Verarbeitungsfluss von ViewGroup: Zunächst muss ein Strukturmodellkonzept vorhanden sein: ViewGroup und View bilden eine Baumstruktur. Die oberste Ebene ist die ViewGroup der Aktivität. Es gibt mehrere ViewGroup-Knoten Darunter befinden sich mehrere ViewGroup-Knoten oder View-Knoten usw. Wie im Bild gezeigt:

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

Wenn ein Touch-Ereignis (als Beispiel ein Touch-Ereignis) den Stammknoten, also die ViewGroup von Active, erreicht, wird es der Reihe nach zugestellt. Der Übermittlungsprozess erfolgt durch Aufrufen. Implementiert durch die DispatchTouchEvent-Methode der Unteransicht (ViewGroup). Vereinfacht ausgedrückt durchläuft die ViewGroup die darin enthaltenen Unteransichten und ruft die „dispatchTouchEvent“-Methode jeder Ansicht auf. Wenn die Unteransicht eine „ViewGroup“ ist, ruft sie weiterhin die „dispatchTouchEvent“-Methode ihrer internen Ansicht auf, indem sie die „dispatchTouchEvent“-Methode von aufruft ViewGroup. Die Nachrichtenübermittlungssequenz im obigen Beispiel ist wie folgt: ①-②-⑤-⑥-⑦-③-④. Die Methode „dispatchTouchEvent“ ist nur für die Ereignisverteilung verantwortlich. Sie verfügt über einen booleschen Rückgabewert. Wenn der Rückgabewert „true“ ist, wird die sequentielle Zustellung unterbrochen. Wenn im obigen Beispiel das „dispatchTouchEvent“ von ⑤ „true“ zurückgibt, empfängt ⑥-⑦-③-④ dieses Touch-Ereignis nicht. Nehmen wir eine einfache Version des Codes, um unser Verständnis zu vertiefen:

/**
   * 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;
  }

Wie Sie hier sehen können, führt das „dispatchTouchEvent“ von ViewGroup tatsächlich „Verteilungs“-Arbeiten aus, während die „dispatchTouchEvent“-Methode von View keine Verteilungsarbeit durchführt Mit anderen Worten: Das verteilte Objekt ist es selbst und entscheidet, ob das Touch-Ereignis zur Verarbeitung an sich selbst übergeben wird. Die Verarbeitungsmethode ist das onTouchEvent-Ereignis. Tatsächlich ist es der Code, der tatsächlich von der DispatchTouchEvent-Methode der Unteransicht ausgeführt wird so

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

Unter normalen Umständen sollten wir die Methode „dispatchTouchEvent“ in einer normalen Ansicht nicht überschreiben, da sie keine Verteilungslogik ausführt. Wenn das Touch-Ereignis die Ansicht erreicht, sollten wir entscheiden, ob es im onTouchEvent-Ereignis behandelt werden soll.

Wann wird also das onTouchEvent-Ereignis von ViewGroup verarbeitet? Wenn alle Unteransichten der ViewGroup false zurückgeben, wird das onTouchEvent-Ereignis ausgeführt. Da ViewGroup von View erbt, führt es das onTouchEvent-Ereignis tatsächlich aus, indem es die „dispatchTouchEvent“-Methode von View aufruft.

Aus der aktuellen Situation scheint es, dass wir sicherstellen können, dass alle Untersteuerelemente auf dieses Touch-Ereignis reagieren, solange wir für alle onTouchEvents false zurückgeben. Es ist jedoch zu beachten, dass das Touch-Ereignis hier auf das Action_Down-Ereignis, also das Touch-Press-Ereignis, beschränkt ist, während Aciton_UP und Action_MOVE nicht ausgeführt werden. Tatsächlich sollte ein vollständiges Touch-Ereignis aus einem Abwärts-, einem Aufwärts- und mehreren Bewegungen bestehen. Der Down-Modus wird über „dispatchTouchEvent“ verteilt. Der Zweck der Verteilung besteht darin, die Ansicht zu finden, die wirklich die vollständige Touch-Anfrage verarbeiten muss. Wenn das onTouchEvent-Ereignis einer Ansicht oder ViewGroup „true“ zurückgibt, bedeutet dies, dass es die Ansicht ist, die diese Anforderung tatsächlich verarbeiten möchte, und dass nachfolgende Aciton_UP- und Action_MOVE-Vorgänge von ihr verarbeitet werden. Wenn das onTouchEvent aller untergeordneten Ansichten false zurückgibt, wird diese Touch-Anfrage von der Root-ViewGroup, also der Aktivität selbst, verarbeitet.

Sehen Sie sich die verbesserte DispatchTouchEvent-Methode von ViewGroup an

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 verfügt auch über ein onInterceptTouchEvent. Sie können anhand des Namens erkennen, dass es sich um ein Abfangereignis handelt. Dieses Abfangereignis muss in zwei Situationen erklärt werden:

1. Wenn wir im onInterceptTouchEvent einer ViewGroup „true“ zurückgeben und die Aktion für das Touch-Ereignis „Down“ ist, bedeutet dies, dass alle von der ViewGroup ausgegebenen Vorgänge dies tun be Intercept it In diesem Fall ist mTarget immer null, da mTarget im Down-Ereignis ein Wert zugewiesen wird. Da mTarge null ist, wird das onTouchEvent-Ereignis der ViewGroup ausgeführt. In diesem Fall kann die ViewGroup direkt als View behandelt werden.

2. Wenn wir uns im onInterceptTouchEvent einer ViewGroup befinden, geben alle Touch-Ereignisse, deren Aktion „Down“ ist, „false“ zurück, und andere geben „True“ zurück. In diesem Fall kann das Down-Ereignis normal verteilt werden Gibt „false“ zurück, dann ist mTarget noch leer, keine Auswirkung. Wenn eine Unteransicht „true“ zurückgibt und mTarget ein Wert zugewiesen wird, wird bei der Verteilung von Action_Move und Aciton_UP an die ViewGroup ein MotionEvent von Action_Delete an mTarget verteilt und gleichzeitig der Wert von mTarget gelöscht, sodass die Der nächste Action_Move (wenn der vorherige Vorgang nicht UP ist) wird von onTouchEvent der ViewGroup verarbeitet.

Situation 1 wird häufiger verwendet, während Situation 2 noch nicht gefunden wurde.

Um es von Anfang bis Ende zusammenzufassen:

1. Es gibt nur zwei Protagonisten bei der Touch-Ereignisverteilung: ViewGroup und View. ViewGroup enthält drei verwandte Ereignisse: onInterceptTouchEvent, DispatchTouchEvent und onTouchEvent. View enthält zwei verwandte Ereignisse: „dispatchTouchEvent“ und „onTouchEvent“. Unter diesen erbt ViewGroup von View.

2. ViewGroup und View bilden eine Baumstruktur und der Wurzelknoten ist eine in der Aktivität enthaltene ViwGroup.

3. Touch-Ereignisse bestehen aus Action_Down, Action_Move und Aciton_UP. In einem vollständigen Touch-Ereignis gibt es nur ein Down- und Up-Ereignis und es gibt mehrere Moves, die 0 sein können.

4. Wenn Acitivty das Touch-Ereignis empfängt, durchläuft es die Unteransicht, um das Down-Ereignis zu verteilen. ViewGroup-Durchquerung kann als rekursiv angesehen werden. Der Zweck der Verteilung besteht darin, die Ansicht zu finden, die dieses vollständige Berührungsereignis tatsächlich verarbeitet. Diese Ansicht gibt im onTouchuEvent-Ergebnis „true“ zurück.

5. Wenn eine Unteransicht „true“ zurückgibt, wird die Verteilung des Down-Ereignisses gestoppt und die Unteransicht wird in der ViewGroup aufgezeichnet. Die nachfolgenden Move- und Up-Ereignisse werden direkt von der Unteransicht verarbeitet. Da die Unteransicht in der ViewGroup in der mehrschichtigen ViewGroup-Knotenstruktur gespeichert wird, speichert die ViewGroup der oberen Ebene das ViewGroup-Objekt dort, wo sich die Ansicht befindet, die das Ereignis tatsächlich verarbeitet: Zum Beispiel in der Struktur von ViewGroup0-ViewGroup1 -TextView, TextView gibt true zurück und wird in ViewGroup1 gespeichert. ViewGroup1 gibt ebenfalls true zurück und wird in ViewGroup0 gespeichert. Wenn die Ereignisse „Move“ und „UP“ eintreffen, werden sie zuerst von ViewGroup0 an ViewGroup1 und dann von ViewGroup1 an TextView übergeben.

6. Wenn nicht alle Unteransichten in der ViewGroup das Down-Ereignis erfassen, wird das onTouch-Ereignis der ViewGroup selbst ausgelöst. Der Auslöser besteht darin, die Funktion super.dispatchTouchEvent aufzurufen, bei der es sich um die DispatchTouchEvent-Methode der übergeordneten Klasse View handelt. Wenn nicht alle Unteransichten verarbeitet werden, wird die onTouchEvent-Methode der Aktivität ausgelöst.

7.onInterceptTouchEvent hat zwei Funktionen: 1. Abfangen der Verteilung von Down-Ereignissen. 2. Stoppen Sie die Übermittlung von Up- und Move-Ereignissen an die Zielansicht, sodass die ViewGroup, in der sich die Zielansicht befindet, die Up- und Move-Ereignisse erfasst.
Ergänzung:

„Berührungsereignisse bestehen aus Action_Down, Action_Move und Aciton_UP. In einem vollständigen Berührungsereignis gibt es nur ein Ab- und ein Aufwärtsereignis und es gibt mehrere Bewegungen, die 0 sein können.“ , hier Darüber hinaus kann es tatsächlich 0 UP-Ereignisse geben.
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für alle hilfreich ist, um den Touch-Ereignisverteilungsmechanismus zu verstehen.

Weitere Artikel zum Verständnis des Android Touch-Ereignisverteilungsmechanismus in 30 Minuten finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn