問題描述
我有一個包含兩個 EditText
的活動.我在第二個 EditText
字段上調用 ??requestFocus
因為默認情況下焦點轉到第一個.焦點似乎在第二個字段中(第二個獲得突出顯示的邊框),但是如果我們嘗試使用硬件鍵盤輸入任何字符,文本會出現(xiàn)在第一個 EditText
控件中.任何想法為什么會發(fā)生?
I have an activity with two EditText
s. I am calling the requestFocus
on the second EditText
field since by default the focus goes to the first one. The focus appears to be in the second field (the second one gets the highlighted border), but if we try to enter any characters using the hardware keyboard the text appears in the first EditText
control. Any ideas why it would be happening?
推薦答案
很難說這是否是你的問題,但也不是不可能.
It's hard to tell whether this was your problem, but it's not unlikely.
TL;DR:永遠不要從 onFocusChanged()
調用中調用像 requestFocus()
這樣的焦點更改方法.
TL;DR: Never call focus-changing methods like requestFocus()
from inside a onFocusChanged()
call.
問題在于 ViewGroup.requestChildFocus()
,其中包含:
The issue lies in ViewGroup.requestChildFocus()
, which contains this:
// We had a previous notion of who had focus. Clear it.
if (mFocused != child) {
if (mFocused != null) {
mFocused.unFocus();
}
mFocused = child;
}
在私有字段 mFocused
中,ViewGroup 存儲當前具有焦點的子視圖(如果有).
Inside the private field mFocused
a ViewGroup stores the child view that currently has focus, if any.
假設您有一個 ViewGroup VG
,其中包含三個可聚焦視圖(例如 EditTexts)A
、B
和 C代碼>.
Say you have a ViewGroup VG
that contains three focusable views (e.g. EditTexts) A
, B
, and C
.
您已向 A
添加了一個 OnFocusChangeListener
(可能不是直接的,而是嵌套在其中的某處)在 B.requestFocus()
時調用 B.requestFocus()
code>A失去焦點.
You have added an OnFocusChangeListener
to A
that (maybe not directly, but somewhere nested inside) calls B.requestFocus()
when A
loses focus.
現(xiàn)在假設A
有焦點,用戶點擊C
,導致A
丟失,C
獲得焦點.因為 VG.mFocused
當前是 A
,所以 VG.requestChildFocus(C, C)
的上面部分然后翻譯成這樣:
Now imagine that A
has focus, and the user taps on C
, causing A
to lose and C
to gain focus. Because VG.mFocused
is currently A
, the above part of VG.requestChildFocus(C, C)
then translates to this:
if (A != C) {
if (A != null) {
A.unFocus(); // <-- (1)
}
mFocused = C; // <-- (3)
}
A.unFocus()
在這里做了兩件重要的事情:
A.unFocus()
does two important things here:
它將
A
標記為不再具有焦點.
It marks
A
as not having focus anymore.
它會調用你的焦點變化監(jiān)聽器.
It calls your focus change listener.
在該偵聽器中,您現(xiàn)在調用 B.requestFocus()
.這會導致 B
被標記為具有焦點,然后調用 VG.requestChildFocus(B, B)
.因為我們仍然深入我用 (1)
標記的調用,所以 mFocused
的值仍然是 A
,因此這個內部調用如下所示:
In that listener, you now call B.requestFocus()
. This causes B
to be marked as having focus, and then calls VG.requestChildFocus(B, B)
. Because we're still deep inside the call I've marked with (1)
, the value of mFocused
is still A
, and thus this inner call looks like this:
if (A != B) {
if (A != null) {
A.unFocus();
}
mFocused = B; // <-- (2)
}
這一次,對 A.unFocus()
的調用沒有做任何事情,因為 A
已經被標記為未聚焦(否則我們將進行無限遞歸這里).此外,沒有任何事情將 C
標記為未聚焦,這是 實際上 現(xiàn)在具有焦點的視圖.
This time, the call to A.unFocus()
doesn't do anything, because A
is already marked as unfocused (otherwise we'd have an infinite recursion here). Also, nothing happens that marks C
as unfocused, which is the view that actually has focus right now.
現(xiàn)在是 (2)
,它將 mFocused
設置為 B
.經過更多的工作,我們終于從 (1)
處的調用返回,因此在 (3)
處,現(xiàn)在設置了 mFocused
的值到 C
,覆蓋之前的更改.
Now comes (2)
, which sets mFocused
to B
. After some more stuff, we finally return from the call at (1)
, and thus at (3)
the value of mFocused
is now set to C
, overwriting the previous change.
所以現(xiàn)在我們最終進入了一個不一致的狀態(tài).B
和 C
都認為他們有焦點,VG
認為 C
是有焦點的孩子.
So now we end up with an incosistent state. B
and C
both think they have focus, VG
considers C
to be the focused child.
特別是,按鍵以 C
結束,并且用戶不可能將焦點切換回 B
,因為 >B
認為它已經有了焦點,因此不對焦點請求做任何事情;最重要的是,它不調用VG.requestChildFocus
.
In particular, keypresses end up in C
, and it is impossible for the user to switch focus back to B
, because B
thinks it already has focus and thus doesn't do anything on focus requests; most importantly, it does not call VG.requestChildFocus
.
推論:您也不應該在 OnFocusChanged
處理程序中依賴 hasFocus()
調用的結果,因為在該調用中焦點信息不一致.
Corollary: You also shouldn't rely on results from hasFocus()
calls while inside an OnFocusChanged
handler, because the focus information is inconsistent while inside that call.
這篇關于多個 EditTexts 的焦點問題的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!