Android View、View Groupイベント配信
8490 ワード
以前にも関連資料を見たことがあり、使ったことも少なくありませんが、覚えておいてください.ViewがDrawableを継承していることを理解してほしいです.Callback, KeyEvent.Callback, AccessibilityEventSource
ViewRootImpl frameworks/base/core/java/android/view/ViewRootImpl.java
View frameworks/base/core/java/android/view/View.java
イベントの転送(最外層のviewから最初に取得)
ViewGroup - ViewGroup - view
Viewでのメソッドイベントの配布
イベントブロック(デフォルトはfalseを返します)
イベント処理(デフォルトはfalseを返します)
*デフォルトの配布と処理を組み合わせると、閉ループに似ています*1.1最上位の親ViewのdispatchTouchEventにイベント配布を行います.
true自己処理(onTouchEventに入る)falseアクセス(メソッドonInterceptTouchEvent)イベントをブロックするかどうかを確認ブロックするtrue-(本ViewonTouchEventに入る)ブロックしないでfalseに戻る-(サブViewに送る)
1.2子View同一判断
1.3ビューが自分に子ビューがないことに気づいた場合、自分で処理します.
2 2.1子ViewのonTouchEvent
false(処理を行わない)onTouchEventイベントを返すと親Viewに渡され、親ViewのonTouchEventが戻りtrue(処理を行う)が自身に渡されたonTouchEvent処理を受け入れるビューがブロックされ、onTouchEvent が処理される
1.ソースViewがイベントメッセージの1.1 viewをどのように取得するかの初期化
1.2 attachInfoの取得
1.3 View RootImplの取得
1.4 ViewのdispatchPointerEvent(これが伝わるポイントです)、dispatchTouchEventを得てMotionEventを得る
1.5次はdispatchTouchEvent、次は他にも伝わります
ViewRootImpl frameworks/base/core/java/android/view/ViewRootImpl.java
View frameworks/base/core/java/android/view/View.java
イベントの転送(最外層のviewから最初に取得)
ViewGroup - ViewGroup - view
Viewでのメソッドイベントの配布
public boolean dispatchTouchEvent(MotionEvent ev)
イベントブロック(デフォルトはfalseを返します)
public boolean onInterceptTouchEvent(MotionEvent ev)
イベント処理(デフォルトはfalseを返します)
public boolean onTouchEvent(MotionEvent ev)
*デフォルトの配布と処理を組み合わせると、閉ループに似ています*1.1最上位の親ViewのdispatchTouchEventにイベント配布を行います.
true自己処理(onTouchEventに入る)falseアクセス(メソッドonInterceptTouchEvent)イベントをブロックするかどうかを確認ブロックするtrue-(本ViewonTouchEventに入る)ブロックしないでfalseに戻る-(サブViewに送る)
1.2子View同一判断
1.3ビューが自分に子ビューがないことに気づいた場合、自分で処理します.
2 2.1子ViewのonTouchEvent
false(処理を行わない)onTouchEventイベントを返すと親Viewに渡され、親ViewのonTouchEventが戻りtrue(処理を行う)が自身に渡されたonTouchEvent処理を受け入れる
1.ソースViewがイベントメッセージの1.1 viewをどのように取得するかの初期化
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
//
public View(Context context, AttributeSet attrs, int defStyle) {
//
View() {
mResources = null;
}
1.2 attachInfoの取得
/** * @param info the {@link android.view.View.AttachInfo} to associated with * this view */
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
//System.out.println("Attached! " + this);
mAttachInfo = info;
mWindowAttachCount++;
// We will need to evaluate the drawable state at least once.
mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
if (mFloatingTreeObserver != null) {
info.mTreeObserver.merge(mFloatingTreeObserver);
mFloatingTreeObserver = null;
}
if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
mAttachInfo.mScrollContainers.add(this);
mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
}
performCollectViewAttributes(mAttachInfo, visibility);
onAttachedToWindow();
ListenerInfo li = mListenerInfo;
final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
li != null ? li.mOnAttachStateChangeListeners : null;
if (listeners != null && listeners.size() > 0) {
// NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
// perform the dispatching. The iterator is a safe guard against listeners that
// could mutate the list by calling the various add/remove methods. This prevents
// the array from being modified while we iterate it.
for (OnAttachStateChangeListener listener : listeners) {
listener.onViewAttachedToWindow(this);
}
}
int vis = info.mWindowVisibility;
if (vis != GONE) {
onWindowVisibilityChanged(vis);
}
if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
// If nobody has evaluated the drawable state yet, then do it now.
refreshDrawableState();
}
needGlobalAttributesUpdate(false);
}
1.3 View RootImplの取得
/** * Gets the view root associated with the View. * @return The view root, or null if none. * @hide */
public ViewRootImpl getViewRootImpl() {
if (mAttachInfo != null) {
return mAttachInfo.mViewRootImpl;
}
return null;
}
1.4 ViewのdispatchPointerEvent(これが伝わるポイントです)、dispatchTouchEventを得てMotionEventを得る
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}
1.5次はdispatchTouchEvent、次は他にも伝わります
public boolean dispatchTouchEvent(MotionEvent event) {
if (mInputEventConsistencyVerifier != null) {
//======================================================= mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
return true;
}
//=========================================
if (onTouchEvent(event)) {
return true;
}
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return false;
}