多个 EditTexts 的焦点问题 [英] Focus issue with multiple EditTexts

查看:27
本文介绍了多个 EditTexts 的焦点问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an activity with two EditTexts. 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)ABC.

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.

现在假设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:

  1. 它将 A 标记为不再具有焦点.

  1. It marks A as not having focus anymore.

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

It calls your focus change listener.

在该侦听器中,您现在调用 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 标记为未聚焦,这是 实际上 现在具有焦点的视图.

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.

现在是 (2),它将 mFocused 设置为 B.经过更多的工作,我们终于从 (1) 处的调用返回,因此在 (3) 处,现在设置了 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.

所以现在我们最终进入了一个不一致的状态.BC 都认为他们有焦点,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 的焦点问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆