본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[Android/안드로이드] dispatchTouchEvent vs. onInterceptTouchEvent vs. onTouchEvent vs. OnTouchListener.onTouch 누가 먼저 불릴까?

by 돼지왕 왕돼지 2012. 7. 19.
반응형

안드로이드의 Touch Event 의 전달경로를 정확히 알기 위해서 다음과 같은 실험을 하였다.

준비구조.

(Root) LinearLayout ( ViewGroup )  : Root 라 명명
                   |
                  └---- LinearLayout ( ViewGroup ) : Middle 이라 명명
                                            |
                                           └-------- Button ( View ) : Leaf 라 명명

여기서 Button 은 OnTouchEventListener 등록.


<테스트 코드>



체크 함수들.

View.dispatchTouchEvent( MotionEvent event )
ViewGroup.onInterceptTouchEvent( MotionEvent event )
View.onTouchEvent( MotionEvent event )
View.OnTouchListener.onTouch( MotionEvent event ) 




실험결과


아무처리 하지 않음.

Root.dispatchTouchEvent -> Root.onInterceptTouchEvent
 -> Middle.dispatchTouchEvent -> Middle.onInterceptTouchEvent
   -> Leaf.dispatchTouchEvent -> Leaf.OnTouchListener.onTouch -> Leaf.onTouchEvent

결론

1. ViewGroup 의 dispatchTouchEvent 와 onInterceptTouchEvent 를 먼저 타고, child 로 event 가 전달된다.
 

2. Listener 함수가 먼저 불린 후, 기본 callback 이 불린다.
 

3. 일반 View 의 기본 onTouchEvent 는 event 를 consume 한다.




Middle 의 onInterceptTouchEvent 에서 true 를 return 하도록 함. ( event 소비 )

Root.dispatchTouchEvent -> Root.onInterceptTouchEvent
 -> Middle.dispatchTouchEvent -> Middle.onInterceptTouchEvent -> Middle.onTouchEvent
 -> Root.onTouchEvent

결론

1. ViewGroup 의 onInterceptTouchEvent 는 자식에게 event 전달 하는 것을 가로챈다는 의미일 뿐, 자신의 event flow 는 그대로 탄다. 그래서 onInterceptTouchEvent 에서 event 를 소비했음에도 불구하고, onTouchEvent 가 불린다.
 

2. ViewGroup 의 기본 onTouchEvent 는 event 를 소비하지 않고, 부모에게 전달한다.



Middle 의 dispatchTouchEvent 에서 true 를 return 하도록 함. ( event 소비 )

Root.dispatchTouchEvent -> Root.onInterceptTouchEvent
 -> Middle.dispatchTouchEvent

결론

1. dispatchTouchEvent 는 dispatch 자체를 멈춰버리기 때문에 event flow 자체를 종료시켜버린다.




Middle 의 onInterceptTouchEvent 에서 ACTION_MOVE 일때는 event 를 가로채도록 함.

결론

1. ACTION_DOWN 에서는 onInterceptTouchEvent 에서 event 를 가로채면 자식에게 아무것도 전달되지 않는다.
 

2. ACTION_DOWN 이 아닌 상황에서는 onInterceptTouchEvent 에서 event 를 가로채면 자식에게 ACTION_CANCEL 이 전달된다. 




이제 MotionEvent 가 어떻게 흘러가는지 확실히 알 수 있겠다.
아직도 모르겠다면 실험을 더 해보시길~





반응형

댓글