編輯:Android開發實例
clearFocus 無效?
EditText在focus與非focus的時候,顯示效果是不同的:focus的時候光標是閃的,而且我們通常也會給它設置selector,focus的時候給它加上邊框之類的.
通常當我們觸摸EditText之外的View時,需要清除EditText的焦點.很自然的就會想到EditText.clearFocus(),然而常常並沒有用.(EditText.isFocus()依然是true,光標也依然在跳躍...)
clearFocus的實現
clearFocus的調用棧(重要的部分):
View.clearFocus() -> View.clearFocusInternal() -> { 1. mParent.clearChildFocus(this);// 從該View一直向上遍歷父節點,知道DecorView,作用是將parent(ViewGroup)中存儲的mFocus設置為null,即清除焦點 2. rootViewRequestFocus();// 調用DecorView的requestFocus()方法,作用是找到視圖中的一個View,並將其設置為焦點 }
根據上面列出的調用棧可以看出,清除focus其實包含2個部分的操作:
清除當前當前View的focus標志,並且清除它的祖先節點中存儲的mFocus信息
調用DecorView的requestFocus()方法,重新尋找一個View,並將其設置為focus
requestFocus()的實現
requestFocus(int)支持FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT 4個參數來表示focus的流向,然而事實上傳入的方向參數並沒有作用.(這個其實比較好理解,以FOCUS_RIGHT來說,是該選擇右子樹種的View,還是繪制在右邊的View呢?)
不管傳怎樣的參數,requestFocus()都是以先序遍歷的方式,找到第一個focusInTouchMode的View,並將其設置為焦點.
設置的方式是:
給當前View focus標志(mPrivateFlags)
調用mParent.requestChildFocus()將自己賦值給其父View的mFocus,然後父View再調用mParent.requestChildFocus()一直到DecorView.
這樣從DecorView開始,只要根據mFocus就可以找到真正focus的View
@Override public View findFocus() { if (DBG) { System.out.println("Find focus in " + this + ": flags=" + isFocused() + ", child=" + mFocused); } if (isFocused()) { return this; } if (mFocused != null) { return mFocused.findFocus(); } return null; }
注意:按照requestFocus這種尋找策略,那麼給定一個起始點,那麼尋找到的View將始終相同,也就是說,你多次調用DecorView.requestFocus(),獲得的焦點都是相同的,如果沒有改變視圖層級以及focusable的話.因此當你想讓某個特定的View獲得焦點的話,就應該直接調用它的requestFocus()方法.
tips:對於ViewGroup來說,可以通過descendantFocusability的設置來選擇優先讓parent,還是child獲得焦點.可選值:FOCUS_BEFORE_DESCENDANTS(默認), FOCUS_AFTER_DESCENDANTS, FOCUS_BLOCK_DESCENDANTS.
clearFocus 真的無效嗎?
當然不是,之所以有時候發現EditText.clearFocus()無效,是因為:清除focus之後,還會按照先序遍歷的順序查找一個focusInTouchMode的View,並將其設置為focus,而你的EditText恰好是這第一個符合條件的View.(因此不是沒清除成功,而是清除了之後,又給設置上了!!)
知道了原因之後,解決就很簡單了,找一個在EditText之前的View,將其設置為可獲得焦點的
View.setFocusableInTouchMode(true) android:focusableInTouchMode="true"
如果不知道怎樣找到一個在EditText之前的View的話,那你可以直接選擇它的parent (xxxLayout),因為ViewGroup默認的策略是: FOCUS_BEFORE_DESCENDANTS
判斷是否focus
isFocused(), 它判斷自己是否擁有焦點
hasFocus(), 它判斷自己或著自己的child是否擁有焦點 常用
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
大家好,眾所周知,android裡兩個相同方向的ScrollView是不能嵌套的,那要是有這樣的需求怎麼辦?(這個需求一般都是不懂android的人提出來的)難道
吸引用戶的眼球,是我們至死不渝的追求;第一時間呈現最有價值的信息,簡明大方,告訴客戶,你的選擇是多麼的明智,這正是你尋覓已久的東西。 分組的應用場合還是很多的,有
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩