防止配置更改后通知 onFocus Listener?

Prevent onFocus Listener being notified after configuration change?

我在 FragmentOnCreateView 期间将焦点侦听器附加到 EditText。 如果 EditText 获得焦点,则通知侦听器。到目前为止一切顺利,但是当焦点恢复到新 Fragment 上时,屏幕旋转后会再次通知侦听器。区分由于配置更改和由于真实的人机交互引起的侦听器通知有什么好的做法吗?还是为了防止在由于配置更改而导致焦点更改后通知监听器?

问题很可能与 onViewStateRestored 调用中恢复的焦点状态有关: https://developer.android.com/reference/android/app/Fragment.html#onViewStateRestored(android.os.Bundle)

为避免监听此更改,只需在 onStart 中调用 setOnFocusChangeListener 而不是 onCreateView

onStartonViewStateRestored 之后调用,因此侦听器将不会收到初始通知。

在我回答问题之前,有几点需要澄清。让我们一步一步来:

If the EditText gets focus, the listener is notified.

focusListener 监听获得焦点和失去焦点。

editText.setOnFocusChangeListener { view, hasFocus ->
        if (hasFocus) toast("focus gained") else toast("focus lost")
    }

您可以使用 hasFocus 布尔值决定如何处理每个案例。

the listener is notified again after screen rotation

是否通知它获得焦点或失去焦点?

when the focus is restored on the new Fragment

屏幕旋转后 EditText 是获得焦点还是失去焦点?

Any good practice to distinguish between listener notification due to a configuration change and due to a real human interaction?

您可以尝试使用 this official guide for saving state and this for configuration changes。您可以在 Bundle 中保存一些 boolean 运行CodeInListener = false。在重新创建片段或 activity 期间获取此布尔值。之后修改监听器里面的代码:

editText.setOnFocusChangeListener {view, hasFocus ->
  if (runCodeInListener) {
    if (hasFocus) toast("focus gained") else toast("focus lost")
} else {
    runCodeInListener = true
  }
}

重新创建后监听器不会运行第一次更改EditText焦点时的代码,

Or to prevent the listener from being notified at all after a focus change due to a configuration change?

仅当 EditText 的焦点发生变化时才会调用侦听器。如果我们阻止上述更改,则不会通知听众。您假设此更改是由于配置更改而发生的:由于配置更改导致焦点更改? 但是,还有一点需要澄清。第一次创建该片段时,EditText 是否有焦点?如果是,则它是布局中的第一个可聚焦视图,并且在配置更改后它再次获得焦点

在布局中创建另一个 EditText,在其上设置一些新的侦听器并查看是否在屏幕旋转后也调用此侦听器。如果我的回答是正确的,第二个 EditText 的听众不应该得到通知,因为只有第一个可聚焦的 EditText 应该有焦点。为了防止 EditText 获得焦点,您还可以使用 this or this

这需要一些编辑,所以如果有不清楚的地方请询问。

需要使用 onResume()onStart()在视图恢复之前调用,因此此处注册的侦听器将触发。