多个EditTexts的焦点问题

时间:2010-06-09 04:18:32

标签: android focus android-edittext

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

4 个答案:

答案 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)ABC

OnFocusChangeListener失去焦点时,您已AB.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在这里做了两件重要的事情:

  1. 它标记为B.requestFocus()不再有焦点。

  2. 它会调用您的焦点更改侦听器。

  3. 在那个听众中,你现在打电话给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覆盖之前的改变

    所以现在我们最终会陷入一种不稳定的状态。 CVG都认为自己有重点,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)