首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 事件分發機制:mFirstTouchTarget 含義與攔截邏輯

     編輯:程式設計綜合問答

mFirstTouchTarget 是什麼?

`mFirstTouchTarget` 是 `ViewGroup` 內部的一個鏈表節點(`TouchTarget`),指向第一個消費(處理)了當前觸摸事件序列的子 View。若無子 View 消費事件,則為 `null`。

核心作用

  • 記錄哪個子 View 正在處理該觸摸流(DOWN、MOVE、UP)。
  • 決定 `dispatchTouchEvent` 中是否繼續分發給其他子 View,以及 `onInterceptTouchEvent` 是否被調用。

MOVE/UP 時 `onInterceptTouchEvent` 偶爾不執行的原因

  1. DOWN 事件被子 View 消費(`onTouchEvent` 返回 `true`),`mFirstTouchTarget` 指向該子 View。後續 MOVE/UP 事件直接分發給該子 View,不再走 `onInterceptTouchEvent` 流程(源碼邏輯:`if (mFirstTouchTarget == null) { ... intercept ... }`)。
  2. DOWN 事件未被任何子 View 消費(全部返回 `false` 或無子 View),`mFirstTouchTarget` 為 `null`。此時 ViewGroup 會自行處理,且每次 MOVE/UP 都會調用 `onInterceptTouchEvent` 詢問是否攔截。

源碼關鍵邏輯簡化

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        mFirstTouchTarget = null; // 重置
    }
    boolean intercepted = false;
    if (onInterceptTouchEvent(ev)) { // 只有 mFirstTouchTarget==null 時才進這裡
        intercepted = true;
    }
    if (!intercepted && mFirstTouchTarget == null) {
        // 遍歷子 View 分發
        for (View child : children) {
            if (child.dispatchTouchEvent(ev)) {
                mFirstTouchTarget = new TouchTarget(child);
                break;
            }
        }
    } else if (mFirstTouchTarget != null) {
        // 直接給已捕獲的子 View
        mFirstTouchTarget.child.dispatchTouchEvent(ev);
    }
    return mFirstTouchTarget != null || intercepted;
}

實戰建議

  • 若需在 MOVE/UP 階段動態攔截,必須在 DOWN 時讓 `onInterceptTouchEvent` 返回 `true`,或讓子 View 返回 `false` 使 `mFirstTouchTarget` 保持 `null`。
  • 使用 `requestDisallowInterceptTouchEvent(true)` 可讓子 View 禁止父容器攔截(如 RecyclerView 滑動時)。

理解 `mFirstTouchTarget` 為「首個消費者」的標記,即可掌握事件分發的攔截與分發節奏。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved