日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Android View焦點(diǎn)總結(jié)

Android View焦點(diǎn)

成都創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供四子王網(wǎng)站建設(shè)、四子王做網(wǎng)站、四子王網(wǎng)站設(shè)計(jì)、四子王網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、四子王企業(yè)網(wǎng)站模板建站服務(wù),十年四子王做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。

Android焦點(diǎn)相關(guān)邏輯大部分都在都在View, ViewGroup和FocusFinder三個(gè)類中.

ViewRoot

View對(duì)象都有一個(gè)mParent變量(添加到ViewGroup后), 代指其父容器. 絕大部分View的mParent都是ViewGroup類型, 除了根節(jié)點(diǎn). 一個(gè)Window中View根節(jié)點(diǎn)DecorView的mParent稱為ViewRoot, 在安卓4.0后ViewRoot對(duì)應(yīng)ViewRootImpl, 它不是View的子類, 而是個(gè)ViewParent. ViewRootImpl是連接Window和DecorView的紐帶, View的焦點(diǎn), 按鍵, 布局, 渲染等流程都是從ViewRoot中開(kāi)始的.

View的焦點(diǎn)

基本流程如下

View(包括ViewGroup)獲取焦點(diǎn)都通過(guò)如下三個(gè)方法

View.java

從上面可以看到前兩個(gè)最終會(huì)執(zhí)行到第三個(gè)方法.

***的requestFocusNoSearch先判斷是否可以獲取焦點(diǎn), 然后進(jìn)入下面的***流程:

View.java

上面的流程比較簡(jiǎn)單: 如果當(dāng)前沒(méi)有焦點(diǎn), 先置焦點(diǎn)標(biāo)志, 再通知parent, 然后刷新圖片.

主要的流程在mParent的requestChildFocus里面, 后面會(huì)分析. 那里會(huì)逐層向上修改焦點(diǎn)View并清除原來(lái)有焦點(diǎn)的View的焦點(diǎn)

onFocusChange會(huì)觸發(fā)invalidate刷新, 然后調(diào)用onFocusChangeListener. 默認(rèn)情況每個(gè)View只能設(shè)置一個(gè)onFocusChangeListener, 而開(kāi)發(fā)中經(jīng)常遇到需要設(shè)置多個(gè)Listener的情況, 我們就可以重寫(xiě)onFocusChange方法, 實(shí)現(xiàn)回調(diào)多個(gè)onFocusChangeListener的需求.

ViewGroup的焦點(diǎn)

ViewGroup獲取焦點(diǎn)是在View獲取焦點(diǎn)流程中多了內(nèi)部焦點(diǎn)處理

ViewGroup.java

上面代碼中descendantFocusability決定了是先按View焦點(diǎn)流程處理(自己處理焦點(diǎn))還是先把給子View處理

FOCUS_BLOCK_DESCENDANTS 不允許子View獲取焦點(diǎn), 那么按照View的流程進(jìn)行

FOCUS_BEFORE_DESCENDANTS 先按照View的流程處理, 如果自己不能獲取焦點(diǎn)則給孩子處理

FOCUS_AFTER_DESCENDANTS 先嘗試給孩子焦點(diǎn), 如果沒(méi)有可獲取焦點(diǎn)再按照View流程自己獲取焦點(diǎn)

默認(rèn)值FOCUS_BEFORE_DESCENDANTS, 我們可以通過(guò)setDescendantFocusability(int d)

設(shè)置

onRequestFocusInDescendants方法是給子類重寫(xiě)使用, 可以控制子View處理焦點(diǎn). 默認(rèn)按照子View順序處理, direction向下或向右則從***個(gè)開(kāi)始, 向上或向左則從***一個(gè)開(kāi)始, 直到某個(gè)子View獲取焦點(diǎn)

注意此方法只在此ViewGroup及其上層View上調(diào)用requestFocus時(shí)會(huì)執(zhí)行到

父容器焦點(diǎn)的處理

在View獲取焦點(diǎn)流程中會(huì)調(diào)用mParent.requestChildFocus, 維護(hù)View樹(shù)上焦點(diǎn)唯一, 在各層ViewGroup中保存有焦點(diǎn)的子View

ViewGroup.java

先清除自己的焦點(diǎn), 如果原來(lái)內(nèi)部有焦點(diǎn), 先清除其焦點(diǎn), 保存獲取焦點(diǎn)的孩子, 然后調(diào)用上一層的requestChildFocus. ***的調(diào)用可知, 這個(gè)方法會(huì)一直調(diào)用到View的樹(shù)的root節(jié)點(diǎn).

在當(dāng)前ViewGroup內(nèi)部, 任何一個(gè)孩子取得焦點(diǎn)都會(huì)執(zhí)行到這個(gè)方法, 因此此方法也是ViewGroup得知孩子焦點(diǎn)變化的方法之一.(可惜不能得知孩子失去焦點(diǎn))

失去焦點(diǎn)或清除焦點(diǎn)

獲取焦點(diǎn)可以是主動(dòng)的, 但失去焦點(diǎn)一般都是被動(dòng)的(見(jiàn)上面的代碼), 因此邏輯相對(duì)簡(jiǎn)單, 只要清除焦點(diǎn)狀態(tài)即可.

ViewGroup.java

View.java

注意上面的方法是默認(rèn)package訪問(wèn)級(jí)別的, 我們無(wú)法重寫(xiě)也不能調(diào)用

也可以主動(dòng)清除焦點(diǎn), 與獲取焦點(diǎn)流程相似

ViewGroup.java

View.java

ViewGroup.java

以上是安卓View系統(tǒng)焦點(diǎn)處理的全部流程和涉及到的方法, ViewRootImpl的requestChildFocus和clearChildFocus實(shí)現(xiàn)我們不需要關(guān)注

另外還有以下一些輔助方法

boolean isFocusable() View是否可以獲取焦點(diǎn)

boolean isFocused() View是否獲取焦點(diǎn)

boolean hasFocus() View/ViewGroup內(nèi)部是否有焦點(diǎn)

View findFocus() 取到View/ViewGroup內(nèi)部的焦點(diǎn)View

View getFocusedChild() 取到ViewGroup內(nèi)部有焦點(diǎn)的子View

View getRootView() 取到根節(jié)點(diǎn)View(一般是DecorView或頂層ViewGroup)

焦點(diǎn)移動(dòng)

除了在代碼里面控制焦點(diǎn), 系統(tǒng)對(duì)沒(méi)有處理的方向鍵等一些按鍵自動(dòng)按照焦點(diǎn)移動(dòng)來(lái)處理, 見(jiàn)下面代碼

ViewRootImpl.java

代碼比較上, 但是主要做了三個(gè)步驟

如果View沒(méi)有處理按鍵, 把上下左右tab等按鍵轉(zhuǎn)換成對(duì)應(yīng)方向

在當(dāng)前焦點(diǎn)View上通過(guò)focusSearch方法查找對(duì)應(yīng)方向的下一個(gè)View

查找到的View調(diào)用requestFocus因此主要的流程在focusSearch中

View.java

普通View查找什么都沒(méi)做, 交給parent來(lái)完成.

ViewGroup.java

ViewRootImpl

我們可以重寫(xiě)focusSearch控制焦點(diǎn)移動(dòng)順序, 而默認(rèn)的焦點(diǎn)移動(dòng)順序由FocusFinder決定

FocusFinder查找焦點(diǎn)

FocusFinder為public的工具類, 主要就兩個(gè)方法, 可以在給定的View內(nèi)在指定方向查找指定View或坐標(biāo)的下一個(gè)焦點(diǎn)如下:

核心邏輯就兩步, 先查找setNextFocusXXId設(shè)置的View, 如果沒(méi)有按照就近算法查找.具體算法不再分析, SDK里面有源碼.

總結(jié)

綜合上面的流程分析, 我們?cè)趯?shí)現(xiàn)自定義View時(shí), 對(duì)焦點(diǎn)的特殊需求有如下思路

requestFocus和clearFocus直接對(duì)View清除或轉(zhuǎn)移焦點(diǎn)

除了onFocusChangeListener, 還可以在onFocusChange方法中實(shí)現(xiàn)一些View失去/獲得焦點(diǎn)時(shí)通知

對(duì)ViewGroup, 如果只需要在子View獲取焦點(diǎn)時(shí)得到通知, 有requestChildFocus方法.

重寫(xiě)onRequestFocusInDescendants方法可以控制某些情景下ViewGroup焦點(diǎn)

控制焦點(diǎn)移動(dòng)可以重寫(xiě)focusSearch方法

另外還有FocusFinder工具和上面的輔助方法.


分享文章:Android View焦點(diǎn)總結(jié)
文章分享:http://www.5511xx.com/article/djgojsi.html