在 OnMouseUp() 方法上使用 unity 3d 中的输入字段时,有没有办法只打开移动键盘?

Is there way to only open the mobile keyboard when using inputfields in unity3d on the OnMouseUp() method?

我想知道是否有一种方法只能在单击 OnMouseUp() 而不是 OnMouseDown() 方法后打开键盘。我尝试修改 inputfield.cs 脚本,但它打不开。

here is the video link

这是可能的,但非常棘手和复杂,尤其是当刚接触 Unity 时。

执行以下操作:

1从编辑器 禁用您希望仅在释放键时打开键盘的 InputFields 上的 interactable。在 InputField 的 "Disabled Color" 上,确保将其更改为白色并将 alpha 更改为完整 (255),这样 InputField 就不会看起来像是被禁用了。


您不必执行下面的剩余步骤,因为它已经在本post末尾的脚本中完成,但下面的步骤向您展示了如何完成。

2。当禁用 InputField interactable 时,它​​不能再接受点击。单击它不会 打开键盘。

您现在必须使用 GraphicRaycaster.Raycast to do a manual UI raycast. The result will be stored in a List of RaycastResult

3。由于您只想在释放点击或触摸时打开键盘,因此将 GraphicRaycaster.Raycast 放在桌面设备的 if (Input.GetKeyUp(KeyCode.Mouse0)) 和移动设备的 if(Input.GetTouch(0).phase == TouchPhase.Ended) 中。当点击或触摸被释放时,它们都会 return true 在框架上。

4#3中的例子释放点击时,检查InputField是否在RaycastResultresult.GetComponentInParent<InputField>()List中,如果它是一个 InputField,手动 select InputFieldSetSelectedGameObjectOnPointerClick 函数。在此之后,键盘应该在 InputField 上打开,那是在释放键而不是按下时。

之后,在 InputField 上注册 onEndEdit 事件。

5。当调用onEndEdit事件时,使用DeactivateInputField函数取消selectInputField,使用[=35=从onEndEdit事件中注销] 函数然后禁用或将可交互设置回 false.


仅对所有 InputField 执行步骤 #1,您只想在释放单击或触摸时打开键盘,然后创建一个名为“ReleaseInputOpenKeyboard",将下面的脚本复制到其中,然后将其附加到场景中的空游戏对象。移动键盘只会在点击或触摸被释放而不是被按下时显示在 InputField 上。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class ReleaseInputOpenKeyboard: MonoBehaviour
{
    GraphicRaycaster m_Raycaster;
    EventSystem m_EventSystem;

    List<GameObject> inputFieldProcessedThisFrame = new List<GameObject>();

    void Start()
    {
        m_Raycaster = GameObject.Find("Canvas").GetComponent<GraphicRaycaster>();
        //Fetch the Event System from the Scene
        m_EventSystem = FindObjectOfType<EventSystem>();
    }


    void Update()
    {
#if UNITY_STANDALONE || UNITY_EDITOR
        //DESKTOP COMPUTERS
        if (Input.GetKeyUp(KeyCode.Mouse0))
        {
            SelectInputField();
        }
#else
        if ((Input.touchCount > 0) && (Input.GetTouch(0).phase == TouchPhase.Ended))
        {
            SelectInputField();
        }
#endif
    }

    void SelectInputField()
    {
        //Set up the new Pointer Event
        PointerEventData m_PointerEventData = new PointerEventData(m_EventSystem);
        //Set the Pointer Event Position to that of the mouse position
        m_PointerEventData.position = Input.mousePosition;

        //Create a list of Raycast Results
        List<RaycastResult> results = new List<RaycastResult>();

        //Raycast using the Graphics Raycaster and mouse click position
        m_Raycaster.Raycast(m_PointerEventData, results);

        //For every result returned, output the name of the GameObject on the Canvas hit by the Ray
        foreach (RaycastResult result in results)
        {
            InputField ipf = result.gameObject.GetComponentInParent<InputField>();
            //Check if object hit is an InputField and make sure we have not processed this object this frame
            if (ipf && !inputFieldProcessedThisFrame.Contains(ipf.gameObject))
            {
                Debug.Log("Hit " + ipf.gameObject.name);

                //Mark this InputField as processed
                inputFieldProcessedThisFrame.Add(ipf.gameObject);

                //Enable interactable
                ipf.interactable = true;

                //Focus on the InputField
                ActivateInputField(ipf, m_EventSystem);

                //Add event to detect when the Input is deselected
                ipf.onEndEdit.AddListener(delegate { OnInputEnd(ipf); });
            }
        }

        //Reset processed InputField
        if (inputFieldProcessedThisFrame.Count > 0)
            inputFieldProcessedThisFrame.Clear();
    }

    void ActivateInputField(InputField ipf, EventSystem evSys)
    {
        evSys.SetSelectedGameObject(ipf.gameObject, new BaseEventData(evSys));
        ipf.OnPointerClick(new PointerEventData(evSys));
    }


    //Detects when InputField is deselected then disable interactible
    void OnInputEnd(InputField ipf)
    {
        StartCoroutine(OnInputEndCOR(ipf));
    }

    IEnumerator OnInputEndCOR(InputField ipf)
    {
        //Disable interactable then remove event
        ipf.DeactivateInputField();
        ipf.onEndEdit.RemoveAllListeners();

        /*Wait until EventSystem is no longer in selecting mode
         This prevents the "Attempting to select while already selecting an object" error
         */
        while (EventSystem.current.alreadySelecting)
            yield return null;

        ipf.interactable = false;
    }
}