>  기사  >  Java  >  30분 안에 Android Touch 이벤트 배포 메커니즘 이해

30분 안에 Android Touch 이벤트 배포 메커니즘 이해

高洛峰
高洛峰원래의
2017-01-16 16:46:051201검색

터치 이벤트 배포의 주역은 ViewGroup과 View 단 두 가지뿐입니다. Activity의 Touch 이벤트는 실제로 내부 ViewGroup의 Touch 이벤트를 호출하며 ViewGroup으로 직접 처리될 수 있습니다.

View는 ViewGroup에 속하며, ViewGroup은 다른 ViewGroup에도 속할 수 있습니다. 이때 내부 ViewGroup은 View로 분석됩니다.

ViewGroup에는 onInterceptTouchEvent, dispatchTouchEvent 및 onTouchEvent의 세 가지 관련 이벤트가 있습니다. View와 관련된 이벤트는 디스패치TouchEvent와 onTouchEvent 두 가지뿐입니다.

먼저 ViewGroup의 처리 흐름을 분석합니다. 먼저 구조적 모델 개념이 있어야 합니다. ViewGroup과 View는 트리 구조를 형성합니다. 아래에는 여러 개의 ViewGroup 노드가 있습니다. 그 아래에는 여러 개의 ViewGroup 노드 또는 View 노드가 있습니다. 그림과 같이

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

Touch 이벤트(예를 들어 터치 이벤트)가 루트 노드, 즉 Active의 ViewGroup에 도달하면 순차적으로 전달됩니다. 전달 프로세스는 하위 보기(ViewGroup)의 dispatchTouchEvent 메소드에 의해 Implemented를 호출하는 것입니다. 간단히 말해서, ViewGroup은 포함된 하위 보기를 순회하고 각 보기의 dispatchTouchEvent 메서드를 호출합니다. 하위 보기가 ViewGroup인 경우에는 의 dispatchTouchEvent 메서드를 호출하여 내부 보기의 dispatchTouchEvent 메서드를 계속 호출합니다. ViwGroup. 위 예의 메시지 전달 순서는 ①- ②-⑤- ⑥ - ⑦- ③ - ④ 입니다. dispatchTouchEvent 메서드는 부울 반환 값만 담당합니다. 반환 값이 true이면 순차적 전달이 중단됩니다. 위의 예에서 ⑤의 dispatchTouchEvent가 true를 반환하면 6-7-3-4는 이 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 메서드는 배포 작업을 수행하지 않거나 배포 작업을 수행하는 것을 볼 수 있습니다. object 자체이며, 터치 이벤트를 자신에게 넘겨줄지 여부를 결정하며, 처리 방법은 onTouchEvent 이벤트입니다. 실제로 하위 View의 dispatchTouchEvent 메서드에서 실제로 실행되는 코드는 다음과 같습니다

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

일반적인 상황에서는 배포 논리를 수행하지 않기 때문에 일반 View에서 dispatchTouchEvent 메서드를 재정의해서는 안 됩니다. Touch 이벤트가 View에 도달하면 onTouchEvent 이벤트에서 이를 처리할지 여부를 결정해야 합니다.

그럼 ViewGroup의 onTouchEvent 이벤트는 언제 처리되나요? ViewGroup의 모든 하위 보기가 false를 반환하면 onTouchEvent 이벤트가 실행됩니다. ViewGroup은 View를 상속하므로 View의 dispatchTouchEvent 메서드를 호출하여 실제로 onTouchEvent 이벤트를 실행합니다.

현재 상황으로 볼 때 모든 onTouchEvents에 false를 반환하는 한 모든 하위 컨트롤이 이 Touch 이벤트에 응답하도록 할 수 있는 것 같습니다. 하지만 여기서의 Touch 이벤트는 Action_Down 이벤트, 즉 터치 누르기 이벤트로 제한되며 Aciton_UP 및 Action_MOVE는 실행되지 않는다는 점에 유의해야 합니다. 실제로 완전한 터치 이벤트는 아래로, 위로 및 여러 동작으로 구성되어야 합니다. 다운 모드는 dispatchTouchEvent를 통해 배포됩니다. 배포의 목적은 전체 터치 요청을 처리하는 데 실제로 필요한 보기를 찾는 것입니다. View 또는 ViewGroup의 onTouchEvent 이벤트가 true를 반환하면 실제로 이 요청을 처리하려는 View이고 후속 Aciton_UP 및 Action_MOVE가 View에 의해 처리된다는 의미입니다. 모든 하위 보기의 onTouchEvent가 false를 반환하면 이 터치 요청은 루트 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가 있습니다. 이름에서 이것이 가로채기 이벤트임을 알 수 있습니다. 이 차단 이벤트는 두 가지 상황으로 설명되어야 합니다.

1. ViewGroup의 onInterceptTouchEvent에서 true를 반환하고 Touch 이벤트에 대한 Action이 Down인 경우 ViewGroup에서 실행된 모든 작업이 이 경우 mTarget은 Down 이벤트에 값이 할당되므로 mTarget은 항상 null이 됩니다. mTarge가 null이므로 ViewGroup의 onTouchEvent 이벤트가 실행됩니다. 이 경우 ViewGroup은 View로 직접 처리될 수 있습니다.

2. 특정 ViewGroup의 onInterceptTouchEvent에 있는 경우 Action이 Down인 모든 Touch 이벤트는 True를 반환하고, 이 경우 자식이 모두 View하면 Down 이벤트가 정상적으로 배포될 수 있습니다. false를 반환하면 mTarget은 여전히 ​​비어 있고 영향이 없습니다. 하위 View가 true를 반환하고 mTarget에 값이 할당되면 Action_Move와 Aciton_UP이 ViewGroup에 배포될 때 Action_Delete의 MotionEvent가 mTarget에 배포되고 동시에 mTarget의 값이 지워지므로 다음 Action_Move(이전 작업이 UP이 아닌 경우)는 ViewGroup의 onTouchEvent에 의해 처리됩니다.

상황 1이 더 자주 사용되는 반면, 상황 2는 아직 발견되지 않았습니다.

처음부터 끝까지 요약하자면:

1. 터치 이벤트 배포의 주인공은 ViewGroup과 View 두 가지뿐입니다. ViewGroup에는 onInterceptTouchEvent, dispatchTouchEvent 및 onTouchEvent라는 세 가지 관련 이벤트가 포함되어 있습니다. View에는 두 가지 관련 이벤트(dispatchTouchEvent 및 onTouchEvent)가 포함되어 있습니다. 그 중 ViewGroup은 View를 상속받습니다.

2. ViewGroup과 View는 트리 구조를 형성하며, 루트 노드는 Activity 내에 포함된 ViwGroup입니다.

3. 터치 이벤트는 Action_Down, Action_Move, Aciton_UP으로 구성됩니다. 완전한 터치 이벤트에는 Down과 Up이 하나만 있고 Move는 0개일 수 있습니다.

4. Activty는 Touch 이벤트를 수신하면 하위 뷰를 순회하여 Down 이벤트를 배포합니다. ViewGroup 순회는 재귀적으로 볼 수 있습니다. 배포의 목적은 이 전체 터치 이벤트를 실제로 처리하는 보기를 찾는 것입니다. 이 보기는 onTouchuEvent 결과에서 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에는 두 가지 기능이 있습니다. 1. Down 이벤트의 배포를 차단합니다. 2. 대상 뷰가 위치한 ViewGroup이 Up 및 Move 이벤트를 캡처하도록 대상 뷰에 대한 Up 및 Move 이벤트 전달을 중지합니다.
보충:

"터치 이벤트는 Action_Down, Action_Move, Aciton_UP으로 구성됩니다. 완전한 터치 이벤트에는 Down 및 Up이 하나만 있고 Move가 여러 개 있으며 0이 될 수 있습니다." , 여기 이외에도 실제로 UP 이벤트가 0개 있을 수 있습니다.
위 내용은 이 글의 전체 내용입니다. 모든 분들이 터치 이벤트 배포 메커니즘을 이해하는 데 도움이 되기를 바랍니다.

30분 안에 Android Touch 이벤트 배포 메커니즘 이해와 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.