안 드 로 이 드 의 이벤트 배포 메커니즘 에 대해 이야기 하 다.
11002 단어 Android이벤트 배포 메커니즘
먼저 모 션 이벤트 가 무엇 인지 소개 합 니 다.모 션 이벤트 란 사용자 가 손가락 으로 휴대 전화 화면 을 만 질 때 발생 하 는 일련의 터치 사건 입 니 다.전형 적 인 터치 사건 은 다음 과 같다.
사건 의 전달 순서:Activity(Window)→ViewGroup→View,즉 사건 은 Activity 에서 아래로 전달 된다.
사건 의 배포 와 관련 된 세 가지 주요 방법:
dispatchTouchEvent:위 에서 아래로 사건 을 전달 합 니 다.그 반환 값 은 하위 View 의 dispatchTouchEvent 방법 과 현재 View 의 onTouchEvent 방법 에 영향 을 받 습 니 다
Activity 의 이벤트 배포 메커니즘
클릭 이벤트 가 발생 했 을 때 이 이 벤트 는 Activity 의 dispatchTouchEvent()방법 으로 가장 먼저 전 달 됩 니 다.
Activity 는 dispatchTouchEvent()방법 에서 getWindow().superDispatchTouchEvent()방법 을 호출 하여 이 벤트 를 Window 의 mDecor(DecorView)에 전달 하고 mDecor 는 superDispatchTouchEvent 방법 을 호출 하여 이 벤트 를 ViewGroup 에 전달 합 니 다.
/**
* :Activity.dispatchTouchEvent()
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
// getWindow().superDispatchTouchEvent(ev) true
// Activity.dispatchTouchEvent() true, 。 : &
// : Activity.onTouchEvent
}
return onTouchEvent(ev);
}
/**
* getWindow().superDispatchTouchEvent(ev)
* :
* a. getWindow() = Window
* b. Window , = PhoneWindow ; Window = PhoneWindow
* c. Window superDispatchTouchEvent() = 1 , PhoneWindow
*/
@Override
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
// mDecor = View(DecorView)
}
/**
* mDecor.superDispatchTouchEvent(event)
* : View(DecorView)
* :
* a. DecorView PhoneWindow
* b. DecorView FrameLayout,
* c. FrameLayout ViewGroup , DecorView = ViewGroup
*/
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
// = ViewGroup dispatchTouchEvent()
// ViewGroup , ViewGroup
}
/**
* Activity.onTouchEvent()
* : View(DecorView)
* :
* a. DecorView PhoneWindow
* b. DecorView FrameLayout,
* c. FrameLayout ViewGroup , DecorView = ViewGroup
*/
public boolean onTouchEvent(MotionEvent event) {
// Activity View /
// : Window
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
// Window true, false
}
ViewGroup 의 이벤트 배포 메커니즘이벤트 가 Activity 에서 ViewGroup 의 dispatchTouchEvent()로 전 달 된 후 ViewGroup 은 먼저 onInterceptTouchEvent()방법 으로 이 사건 을 차단 할 지 여 부 를 판단 합 니 다.(기본적으로 차단 하지 않 고 차단 하려 면 사용자 가 다시 써 야 합 니 다)이 사건 을 차단 하지 않 으 면 ViewGroup 은 모든 하위 View 를 순환 적 으로 옮 겨 다 니 며 현재 이벤트 가 발생 한 View 를 찾 습 니 다.그리고 이 하위 View 의 dispatchTouchEvent()방법 을 호출 하여 이 벤트 를 하위 View 에 나 누 어 처리 합 니 다.
이 이벤트 가 ViewGroup 에 의 해 차단 되 거나 이벤트 가 발생 한 View(이벤트 가 빈 곳 에서 발생 함)를 찾 지 못 하면 ViewGroup 은 onTouchEvent()방법 으로 이 벤트 를 처리 합 니 다.
/**
* :ViewGroup.dispatchTouchEvent()
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
... //
// ViewGroup , onInterceptTouchEvent()
if (disallowIntercept || !onInterceptTouchEvent(ev)) {
// 1:disallowIntercept = ( false), requestDisallowInterceptTouchEvent()
// 2: !onInterceptTouchEvent(ev) = onInterceptTouchEvent()
// a. onInterceptTouchEvent() false( ), true,
// b. onInterceptTouchEvent() true( ), false,
// c. onInterceptTouchEvent() ->> 1
ev.setAction(MotionEvent.ACTION_DOWN);
final int scrolledXInt = (int) scrolledXFloat;
final int scrolledYInt = (int) scrolledYFloat;
final View[] children = mChildren;
final int count = mChildrenCount;
// for , ViewGroup View
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
|| child.getAnimation() != null) {
child.getHitRect(frame);
// View View, View
// ,
if (frame.contains(scrolledXInt, scrolledYInt)) {
final float xc = scrolledXFloat - child.mLeft;
final float yc = scrolledYFloat - child.mTop;
ev.setLocation(xc, yc);
child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
// View dispatchTouchEvent()
// ViewGroup View ( View )
if (child.dispatchTouchEvent(ev)) {
mMotionTarget = child;
return true;
// View dispatchTouchEvent
// , ,dispatchTouchEvent true,
// ViewGroup dispatchTouchEvent() true,
// ViewGroup
}
}
}
}
}
}
boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
(action == MotionEvent.ACTION_CANCEL);
if (isUpOrCancel) {
mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
}
final View target = mMotionTarget;
// ( View ) / ( onInterceptTouchEvent(), true)
if (target == null) {
ev.setLocation(xf, yf);
if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
ev.setAction(MotionEvent.ACTION_CANCEL);
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
}
return super.dispatchTouchEvent(ev);
// ViewGroup dispatchTouchEvent(), View.dispatchTouchEvent()
// ViewGroup onTouch() ->> onTouchEvent() ->> performClick() ->> onClick(), , ( View View.dispatchTouchEvent())
// : View dispatchTouchEvent()
}
...
}
/**
* ViewGroup.onInterceptTouchEvent()
* :
* :
* a. true = , ( , onInterceptTouchEvent(), true)
* b. false = ( )
*/
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
View 의 이벤트 배포 메커니즘이벤트 가 ViewGroup 에서 View 의 dispatchTouchEvent()로 전 달 된 후에 가장 먼저 실행 되 는 것 은 View 의 onTouch()방법 이다.onTouch()방법 은 View 의 OnTouch Listener 인터페이스 에서 정 의 된 방법 입 니 다.사용자 가 View 에 감청 을 등록 하면 사용자 가 화면 을 만 질 때 이 방법 을 실행 합 니 다.이 방법 은 기본적으로 false 로 돌아 갑 니 다.사용자 가 다시 써 야 합 니 다.
onTouch()방법 이 false 로 되 돌아 와 야 View 의 onTouch Event()방법 을 실행 할 수 있 습 니 다.그리고 상황 에 따라 performClick()방법 을 호출 하고 performClick()방법 에 따라 onClick()방법 을 호출 합 니 다.
/**
* :View.dispatchTouchEvent()
*/
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
// : 3 ,dispatchTouchEvent() true; onTouchEvent()
// 1. mOnTouchListener != null
// 2. (mViewFlags & ENABLED_MASK) == ENABLED
// 3. mOnTouchListener.onTouch(this, event)
// 3
/**
* 1:mOnTouchListener != null
* :mOnTouchListener View.setOnTouchListener()
*/
public void setOnTouchListener(OnTouchListener l) {
mOnTouchListener = l;
// Touch ,mOnTouchListener ( )
}
/**
* 2:(mViewFlags & ENABLED_MASK) == ENABLED
* :
* a. enable
* b. View enable, true
*/
/**
* 3:mOnTouchListener.onTouch(this, event)
* : Touch onTouch(); , ( Button )
*/
button.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
// onTouch() true, , View.dispatchTouchEvent() true,
// onTouch() false, , View.dispatchTouchEvent() If, onTouchEvent(event)
View 의 onTouch Event()가 true 로 돌아 가면 이 사건 을 소모 하면 사건 의 배 포 는 여기 서 끝 납 니 다.false 로 돌아 가면 아래 에서 위로 View Group 과 Activity 의 onTouchEvent()방법 으로 사건 을 처리 합 니 다.특히 Activity 의 onTouch Event()방법 은 사건 을 처리 해 야 한다.이로써 사건 의 배 포 는 끝났다.
이상 은 안 드 로 이 드 의 이벤트 배포 체제 에 대한 상세 한 내용 입 니 다.안 드 로 이 드 이벤트 배포 체제 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.