解碼自定義View-觸摸反饋

  觸摸反饋應該是自定義view最簡單的部分了,不過內部的原理是比較複雜的,去了解裏面的核心機制,須要本身去閱讀源碼,才能更好理解整個觸摸機制,固然,知其因此然也是遠遠不夠的,下面我就帶你們瞭解自定義view觸摸機制的難點重點。面試

一. 概念

觸摸反饋就是View對你的用戶的觸摸事件進行自定義,重寫onTouchEvent方法算法

二.自定義單View的觸摸反饋

  • 重寫 onTouchEvent(),在方法內部定製觸摸反饋算法ui

  • 是否消費事件取決於 ACTION_DOWN 事件 或 POINT_DOWN 事件是否返回 爲truespa

  • MotionEventcode

    • getActionMasked() 和 getAction()遞歸

    • POINT_DOWN / POINT_UP 和 getActionIndex()事件

三.觸摸反饋的流程

  • Activity.dispatchEvent()get

    • 遞歸: ViewGroup(View).dispatchTouchEvent()
    • ViewGroup.onInterceptTouchEvent()
    • child.dispatchTouchEvent()
    • super.dispatchTouchEvent()
    • View.onTouchEvent()
  • Activity.onTouchEvent()源碼

四.View.dispatchTouchEvent()

  • 若是設置了 OnTouchListener ,調用 OnTouchListener.onTouch()it

    • 若是 OnTouchListener 消費了該事件,返回 true
    • 若是 OnTouchListener 沒有消費該事件,繼續調用本身的 onTouchEvent 並返回 和 onTouchEvent相同的結果
  • 若是沒有設置OnTouchListener,同上

五.ViewGroup.dispatchTouchEvent()

  • 若是是用戶初次按下 (ACTION_DOWN) ,清空TouchTargets 和 DISALLOW_INTERCEPT 標記

    • 攔截處理 getParent().requestDisallowInterceptTouchEvent()
    • 若是不攔截並非 CANCEL 事件,而且是down 或者 POINT_DOWN ,嘗試把pointer (手指) 經過 touchTarget 分配給子View;而且 若是 分配給 新的子View ,調用 child.dispatchEvent 把 DOWN 事件傳給子View
  • 看有沒有 TouchTargets

    • 若是沒有,調用super.dispatchEvent()
    • 若是有,調用child.dispatchEvent() 把事件傳給對應的子View(若是有的話)
  • 若是是 POINT_UP ,從 TouchTargets 中清除 POINTER 信息;若是 UP 或者 CANCEL 重置狀態

六.TouchTarget

  • 做用: 記錄單view是被哪些 pointer(手指)按下的
  • 結構: 單向鏈表

七.面試題分享

Alibaba 面試題: 有一個 ViewGroup, 而後手指頭接觸 Button ,手指頭滑開了,滑開又鬆手的過程,整個事件發生了什麼?經歷了什麼?

  一開始ViewGroup 會接受到整個事件序列的第一個事件: ACTION_DOWNViewGroup#dispatchTouchEvent 收到ACTION_DOWN 後,

  開始詢問 ViewGroup#onInterceptTouchEvent 是否須要攔截,

  默認狀況下 ViewGroup#onInterceptTouchEvent 返回false 不攔截,開始向下傳遞ACTION_DOWN 事件,

  Buttton#dispatchTouchEvent 收到ACTION_DOWN 詢問onTouchEvent 是否處理,

  Button 默認處理,此後的全部事件序列都直接跨過 ViewGroup#onInterceptTouchEvent 的判斷直接傳遞給Button

  但 ViewGroup#dispatchTouchEvent 會收到全部事件。隨着手指的滑動Button 的座標發生了改變,當手指擡起時觸發 Button#onClick 事件。

八.參考資料

相關文章
相關標籤/搜索