版權聲明:android
本帳號發佈文章均來自公衆號,承香墨影(cxmyDev),版權歸承香墨影全部。算法
未經容許,不得轉載。3d
Android 系統的智能電視,最近兩年基本上愈來愈火了,而在如今手機 App 開發中,都是使用觸摸的模式進行操做,可是在開發智能電視 App 的時候,View 的焦點尋址,就是咱們繞不過去的坎。cdn
那麼,本文就 View 如何控制 Focus,來分析它背後的實現邏輯。blog
在 Android 中,是有一套本身的焦點查找的算法,簡單來講,就近原則,就是按方向就近查找下一個符合條件的 View。接口
若是咱們有對一個 View 焦點控制的需求,須要對這個 View 強制指定它上下左右以後的下一個獲取焦點的 View。能夠經過 View 的屬性來控制,只須要在對應方向上設定咱們須要焦點轉移的下一個 View 的 ID 便可。ci
這些都是最基本的,不是本文的主題。那麼若是沒有設定這些屬性,而 Android 對 View 的就近原則的焦點查找算法,究竟是如何實現的呢?開發
Android 中,是如何作到對 View 焦點的控制呢?源碼
咱們就先從 View 的源碼看起,看看它是如何找到「下一個」位置的 View的,在 View 中,查找下一個應該獲取焦點的 View ,使用的方法是 focusSearch()。it
它須要傳遞一個 direction 參數,這個 direction 就是指定獲取什麼方向上的下一個位置的焦點。
而 View 並不會處理焦點尋址的具體邏輯,而是將焦點的查找委託給 mParent 來實現,mParent 是一個接口,它的實現類是 ViewRootImpl。
ViewRootImlp.focusSearch() 最終又將焦點尋址的任務,交託給 FocusFinder 來處理。
findNextFocus() 中能夠看到,findNextUserSpecifiedFocus() 方法正是用於查找咱們對 View 設定不一樣方向的下一個焦點的 ViewId ,它的優先級是最高的,若是沒有找到,纔會進行 findNextFocus() 經過算法來查找對應的 View。
爲了證明這個說法,咱們先看看 findNextUserSpecifiedFocus() 的源碼。
最終,又調回到 View.findUserSetNextFocus() 方法去尋找。
到這裏也證明了咱們的猜想,確實是經過 direction 來進行 View 的焦點尋址。
再回過頭來看看 findNextFocus() 方法,若是經過 findNextUserSpecifiedFocus() 方法沒有找到咱們指定的 View,就會繼續向下執行。這裏聲明的一個局部變量 focusables 就是用於存放符合算法的全部 View 。
接下來再看看如何向 focusables 這個 List 中,添加符合尋址要求的 View。在 findNextFocus() 中能夠看到,它最終會調用 findNextFocusInAbsoluteDirection() 方法。
從 findNextFocusInAbsoluteDirection() 方法能夠看出,就近原則就是在這裏實現的,經過 View 的座標點,計算出最符合要求的 View ,最終將找到的 View 返回過去。
到這裏,基本就追蹤到 View 對焦點尋址的完整邏輯。最後補一個方法調用的流程圖。
若是有對 View 焦點的控制,能夠考慮經過設置 View 的屬性,還能夠經過重寫 View.focusSearch() 方法,來定製 View 焦點的尋址規則。不過通常而言,不推薦重寫 focusSearch() 方法,只使用屬性控制也能知足咱們的需求。