2010-06-09 64 views
14

我有一个活动与两个EditText s。我在第二个EditText字段上拨打requestFocus,因为默认情况下焦点会转到第一个。焦点似乎在第二个字段中(第二个字段获得突出显示的边框),但如果我们尝试使用硬件键盘输入任何字符,则文本会出现在第一个控件中。任何想法为什么会发生?与多个EditTexts的焦点问题

+2

请发布您的代码,以便我们可以确切地看到您在做什么。 – Harris 2011-07-18 22:20:05

+0

没有更多的信息,这个问题不能以合理的方式回答,它已经坐了很长一段时间没有额外的信息。 – 2011-09-22 21:46:31

回答

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; 
     } 
} 

我清楚的焦点从拥有它的观点,我要求进行对焦并设置变量requestFocus的空。

我相信发生这种情况是因为在我请求焦点时,没有人关注焦点,我的EditText重新获得焦点,活动将焦点转移到下一个视图。希望它对某人有帮助。

19

很难说这是否是你的问题,但这不是不可能的。

TL; DR:决不会从onFocusChanged()调用中调用requestFocus()等焦点更改方法。

问题在于ViewGroup.requestChildFocus(),其中包含此:

// We had a previous notion of who had focus. Clear it. 
if (mFocused != child) { 
    if (mFocused != null) { 
     mFocused.unFocus(); 
    } 

    mFocused = child; 
} 

里面的私有字段​​一个ViewGroup中存储了当前具有焦点,如果任何一个子视图。

假设您有一个ViewGroup VG,其中包含三个可调焦视图(例如EditTexts)ABC

A失去焦点时,您已添加OnFocusChangeListenerA(可能不直接,但嵌入内部某处)调用B.requestFocus()

现在设想A有焦点,并且用户点击C,导致A丢失,并且C获得焦点。由于VG.mFocused目前AVG.requestChildFocus(C, C)上述部分则转化为这样:

if (A != C) { 
    if (A != null) { 
     A.unFocus();   // <-- (1) 
    } 

    mFocused = C;    // <-- (3) 
} 

A.unFocus()在这里所做的两个重要的事情:

  1. 它了标志着A为不受关注。

  2. 它调用你的焦点变化监听器。

在该听众中,您现在拨打B.requestFocus()。这会导致B被标记为有焦点,然后调用VG.requestChildFocus(B, B)。因为我们还在我打上(1)通话深处的​​值仍然A,因此这内心的召唤看起来是这样的:

if (A != B) { 
    if (A != null) { 
     A.unFocus(); 
    } 

    mFocused = B;    // <-- (2) 
} 

这一次,调用A.unFocus()不做任何事情,因为A已被标记为未聚焦(否则我们在这里会有无限递归)。此外,没有任何反应将C标记为未聚焦,这是实际上现在的重点。

现在来到(2),其将​​设置为B。经过一些更多的东西,我们终于从电话(1)返回,因此在(3)的值​​现在设置为C,覆盖以前的变化

所以现在我们结束了一个inc inctent状态。 BC都认为他们有重点,VG认为C是重点儿童。

特别,按键最终在C,这是用户不可能将焦点切换回B,因为B认为它已经集中,因此不会做重点要求任何东西;最重要的是,它的确不是而是请致电VG.requestChildFocus

推论:由于在该调用中焦点信息不一致,所以在OnFocusChanged处理程序中,您也不应该依赖来自hasFocus()调用的结果。

+0

真棒回答...我的问题有点类似于... upvoting – 2014-05-29 15:39:55

+1

很好的答案,但你建议如何解决这个问题。只需发布消息来做到这一点? – 2014-08-29 18:07:54

+0

@RossHambrick是的,你必须在事件处理程序之外,所以这真的是我能想到的唯一解决方案。 – balpha 2014-08-29 18:21:42

4

我找到了解决方案。

里面的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(); 
         } 
        }); 
      } 
     } 
    }); 
+0

在我的情况下没有什么区别。 – Tomislav3008 2016-08-22 09:54:43

+0

@ Tomislav3008你为什么不用代码显示你正在尝试的问题,然后可能是我可以帮你 – 2016-08-23 07:21:27

+0

我设法把我的请求焦点放在focusChange处理程序之外,它是要走的路。我遇到的问题正是balpha解释的,获得了两个editText视图,两个视图都有焦点。也许我的问题是把它放在一个处理程序,而不是一个监听器,我有'((EditText)发件人).Post(新的Runnable(委托{((EditText)发件人).RequestFocus();}));'' – Tomislav3008 2016-08-24 08:56:13