You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2022.3.9f1移动端多输入框切换键盘闪烁问题求助

解决Unity 2022.3.9f1移动端InputField切换时软键盘闪烁问题

这个问题的核心是Unity默认的InputField焦点切换逻辑:当旧输入框失去焦点时,会立即触发软键盘隐藏,新输入框激活时再重新唤起键盘,导致闪烁。要解决这个问题,我们需要拦截这一默认行为,让键盘在输入框切换时保持显示。

方法一:自定义InputField扩展

创建一个继承自Unity内置InputField的自定义组件,重写焦点相关方法来控制键盘状态:

using UnityEngine;
using UnityEngine.UI;

public class PersistentKeyboardInputField : InputField
{
    private static bool _isSwitchingInput = false;

    // 输入框失去焦点时调用
    protected override void OnDeselect(BaseEventData eventData)
    {
        // 如果是在切换到另一个输入框,暂时阻止默认的键盘隐藏逻辑
        if (_isSwitchingInput)
        {
            return;
        }
        base.OnDeselect(eventData);
    }

    // 输入框获得焦点时调用
    public override void OnSelect(BaseEventData eventData)
    {
        // 标记当前正在切换输入框
        _isSwitchingInput = true;
        base.OnSelect(eventData);
        // 延迟一小段时间取消标记,确保旧输入框的OnDeselect已执行完毕
        Invoke(nameof(ResetSwitchFlag), 0.1f);
    }

    private void ResetSwitchFlag()
    {
        _isSwitchingInput = false;
    }

    // 处理点击非输入区域的情况,确保键盘能正常隐藏
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            var pointerEventData = new PointerEventData(EventSystem.current);
            pointerEventData.position = Input.mousePosition;
            var results = new System.Collections.Generic.List<RaycastResult>();
            EventSystem.current.RaycastAll(pointerEventData, results);
            
            bool hitInputField = false;
            foreach (var result in results)
            {
                if (result.gameObject.GetComponent<PersistentKeyboardInputField>() != null)
                {
                    hitInputField = true;
                    break;
                }
            }

            if (!hitInputField && isFocused)
            {
                _isSwitchingInput = false;
                DeactivateInputField();
            }
        }
    }
}

使用时,将场景中原有的InputField组件替换为这个自定义组件即可。

方法二:全局焦点切换监听

如果不想修改InputField组件,可以写一个全局管理脚本,监听EventSystem的焦点变化:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class InputKeyboardManager : MonoBehaviour
{
    private GameObject _lastSelectedInput;

    void OnEnable()
    {
        EventSystem.current.SetSelectedGameObject += OnSelectedGameObjectChanged;
    }

    void OnDisable()
    {
        EventSystem.current.SetSelectedGameObject -= OnSelectedGameObjectChanged;
    }

    private void OnSelectedGameObjectChanged(GameObject selectedObj)
    {
        // 检查新选中的对象是否是InputField
        if (selectedObj?.GetComponent<InputField>() != null)
        {
            // 如果之前选中的也是InputField,阻止旧输入框触发键盘隐藏
            if (_lastSelectedInput?.GetComponent<InputField>() != null)
            {
                var oldInput = _lastSelectedInput.GetComponent<InputField>();
                oldInput.DeactivateInputField(false); // 参数false表示不触发键盘隐藏
            }
        }
        _lastSelectedInput = selectedObj;
    }
}

将这个脚本挂在场景中的任意持久化GameObject上(比如Canvas),它会自动处理所有InputField的焦点切换,避免键盘闪烁。

注意事项

  • 务必在真实移动设备上测试,模拟器的键盘行为可能和真机不一致
  • 上述方法同时兼容iOS和Android平台,无需额外区分
  • 如果使用第三方输入框插件(比如TMPro的InputField),只需将代码中的InputField替换为对应的插件类即可

内容的提问来源于stack exchange,提问作者JohnRaja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 06:00:19