TMP_InputField可以注册一个onSelect回调函数,在InputField选中的时候回调,但在虚拟键盘手动关闭或被返回取消的时候,此时再打开虚拟键盘时,就不会调用onSelect。
原因在于,虚拟键盘有三种关闭的操作方式:
- 第一,是点击虚拟机键盘外部,此时会失去焦点,即LostFocus事件。
- 第二,是手动点击虚拟键盘的关闭按钮,此时什么事件都不触发,只是虚拟键盘隐藏。
- 第三,是使用返回按键,此时会导致取消,即Canceled事件。
有趣的是:
- 第一种,EventSystem.current.currentSelectedGameObject为——null。
- 第二种,EventSystem.current.currentSelectedGameObject为——InputField的gameObject。
- 第三种,EventSystem.current.currentSelectedGameObject为——InputField的gameObject。
所以,再次打开虚拟键盘,只有第一种正确回调onSelect——因为,第二种与第三种,InputField依然保持了选中状态,而再次选中同一个对象,不会响应回调,在InputField的OnPointerDown中可以看到是调用了SetSelectedGameObject。
EventSystem.current.SetSelectedGameObject(base.gameObject, eventData);public void SetSelectedGameObject(GameObject selected, BaseEventData pointer)
{if (m_SelectionGuard){Debug.LogError("Attempting to select " + selected?.ToString() + "while already selecting an object.");return;}m_SelectionGuard = true;if (selected == m_CurrentSelected){m_SelectionGuard = false;return;}ExecuteEvents.Execute(m_CurrentSelected, pointer, ExecuteEvents.deselectHandler);m_CurrentSelected = selected;ExecuteEvents.Execute(m_CurrentSelected, pointer, ExecuteEvents.selectHandler);m_SelectionGuard = false;
}
于此同时,对于这三种情况,关闭虚拟键盘时onDeselect的回调如下:
- 第一种,失去焦点,回调onDeselect,释放选中对象。
- 第二种,手动关闭,不调用onDeselect,不释放选中对象。
- 第三种,返回取消,回调onDeselect,不释放选中对象。
是的,这个返回取消,不能正确释放选中状态,还调用了onDeselect——因为这个onDeselect是被直接代码调用的,而不是通过SetSelectedGameObject触发的。
因此,要解决onSelect不调用的问题,就是关闭虚拟键盘时,手动调用EventSystem.current.SetSelectedGameObject(null)——但这会产生另一个小问题:
就是返回取消的时候,onDeselect会调用两次,即:一次来自SetSelectedGameObject,一次来自InputField自己——而失去焦点的情况,会清除选中状态,所以SetSelectedGameObject已经是null,就不会调用onDeselect。
那么,解决的方法就是——使用onEndEdit来代替onDeselect。