我有两个EditText
的活动。我在第二个requestFocus
字段上调用EditText
,因为默认情况下焦点转到第一个EditText
字段。焦点似乎位于第二个字段中(第二个字段获得突出显示的边框),但如果我们尝试使用硬件键盘输入任何字符,则文本将显示在第一个{{1}}控件中。任何想法为什么会发生?
答案 0 :(得分:27)
很难说这是否是你的问题,但并非不可能。
TL; DR:永远不要在requestFocus()
来电中调用onFocusChanged()
等改变焦点的方法。
问题出在ViewGroup.requestChildFocus()
,其中包含:
// We had a previous notion of who had focus. Clear it.
if (mFocused != child) {
if (mFocused != null) {
mFocused.unFocus();
}
mFocused = child;
}
在私有字段mFocused
内,ViewGroup存储当前具有焦点的子视图(如果有)。
假设您有一个包含三个可聚焦视图的ViewGroup VG
(例如EditTexts)A
,B
和C
。
当OnFocusChangeListener
失去焦点时,您已A
向B.requestFocus()
添加A
(可能不是直接,但嵌套在某处)调用A
。
现在假设C
具有焦点,用户点击A
,导致C
丢失,VG.mFocused
获得焦点。由于A
目前为VG.requestChildFocus(C, C)
,因此if (A != C) {
if (A != null) {
A.unFocus(); // <-- (1)
}
mFocused = C; // <-- (3)
}
的上述部分会转换为:{/ p>
A.unFocus()
A
在这里做了两件重要的事情:
它标记为B.requestFocus()
不再有焦点。
它会调用您的焦点更改侦听器。
在那个听众中,你现在打电话给B
。这会导致VG.requestChildFocus(B, B)
被标记为具有焦点,然后调用(1)
。因为我们仍然在我标记为mFocused
的电话的深处,A
的值仍为if (A != B) {
if (A != null) {
A.unFocus();
}
mFocused = B; // <-- (2)
}
,因此此内部调用如下所示:< / p>
A.unFocus()
这一次,对A
的调用没有做任何事情,因为C
已经标记为未聚焦(否则我们会在此处进行无限递归)。此外,没有任何事情将(2)
标记为未聚焦,这是实际上现在关注的视图。
现在来mFocused
,将B
设置为(1)
。在更多内容之后,我们最终从(3)
的来电回复,因此在mFocused
C
的值现在设置为B
,覆盖之前的改变
所以现在我们最终会陷入一种不稳定的状态。 C
和VG
都认为自己有重点,C
认为C
是专注的孩子。
特别是,按键结束于B
,用户无法将焦点切换回B
,因为VG.requestChildFocus
认为已经有焦点,因此在焦点请求上没有做任何事情;最重要的是,它不调用hasFocus()
。
推论:在OnFocusChanged
处理程序中,您也不应该依赖{{1}}次调用的结果,因为焦点信息在该调用中不一致。
答案 1 :(得分:5)
我找到了解决方案。
在onFocusChange内部不要直接调用requestFocus,而是发布runnable来请求焦点。例如在我的代码下面,
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus == false) {
editText.post(new Runnable() {
@Override
public void run() {
editText.requestFocus();
}
});
}
}
});
答案 2 :(得分:1)
我遇到了同样的问题,我的一个EditText有一个OnFocusListener,当它失去焦点时,我做了一些转换,但如果出现问题,我会再次尝试requestFocus并让用户解决问题。这是问题出现的时候,我最终得到了带焦点的EditText,我尝试用焦点搜索视图,但findFocus()返回null。我找到的唯一解决方案是创建一个EditText变量
private EditText requestFocus;
如果有任何问题,我将EditText设置为该变量,这是我不喜欢的但是它有效,我将OnFocusListener设置为我的活动上的其他视图。当他们获得焦点时,我会这样做
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus)
if(requestFocus != null){
v.clearFocus();
requestFocus.requestFocus();
requestFocus = null;
}
}
我从拥有它的视图中清除焦点,我请求Focus并将变量requestFocus设置为null。
我相信这种情况正在发生,因为在我请求焦点时没有人有焦点,我的EditText重新获得焦点,活动将焦点放在下一个视图上。希望对某人有所帮助。
答案 3 :(得分:0)
尝试使用requestFocus(); http://developer.android.com/reference/android/view/View.html#requestFocus()