Currently, the InputField behavior, if using keyboard/controller is as follows:
Navigate to inputField
It becomes selected & highlighted
Text-entry is active (caret is visible)
You can then hit cancel to back out of the text-entry
inputField is selected & highlighted
Text entry is inactive (caret is invisible)
Now what I’d like to do is have the inputField NOT automatically go into text-entry, just by navigating/selecting it with a controller (while still doing so via mouse). Instead I’d like it to be in the mode it is in when you hit ESC: It is selected and highlighted but text entry is inactive. Once you hit SUBMIT the field moves to text entry mode.
Does anyone know if that’s possible without fiddling with the component code itself? (inheriting etc.)
I’ve tried out a few things to solve this but to no avail, so I’m bumping it.
For example: I tried a script on the same component that runs DeactivateInputField in OnSelect and ActivateInputField in OnSubmit. Or I tried the same with readOnly on the input field. Nothing seemed to do the trick.
Regarding the auto-edit mode:
One way would be to nest the input field under a button and setup explicit navigation between the rest of your UI and the nested button/input field (to avoid auto-navigating from a different UI element to the input field).
The button On Click() would call InputField.Select, thus entering the edit mode.
Regarding the text highlighting:
You could add an event trigger to the button and set it to Select. It would need to call a helper method to edit the appearance of the underlying input field to highlight the text. The same for the OnSelect for the input field, but reversing the effect.
I hate to revive a dead thread but I couldn’t find a solution anywhere and I have found a work around. I don’t really like it but it works and it’s compact.
Add a callback to TMPInputField OnSelect to toggle the enabled bool of the input field off
add an event trigger script to the object, add an OnSelect callback and toggle the enabled bool back on.
This works because TMPro will attempt to activate immediately after invoking the OnSelect callbacks. Usually it will set itself to activate the next frame and there’s nothing to stop it after this point. However, it won’t set itself to activate if enabled is set to false beforehand. Then immediately after it skips this activation the event trigger is hit next and it sets enabled back on so it functions as normal. A hacky solution but it works.
NOTE: this was edited as originally I toggled interactable. This gave the expected behavior, but was causing an error for me, so I changed it to toggle the enabled bool.
I ran into this problem as well and I’m shocked at how Unity has not addressed this properly as it’s such a vital need. If you’re adding controller or console support to your game this non-negotiable. I made a similar fix to the solution (although @horsesNhalo probably has a better solution). I just waited until the end of the frame to set the input to deactive.
I created this script and I attach it to any game object with an InputField component. Heres an example:
public class InputControllerHelper : MonoBehaviour, ISelectHandler, ISubmitHandler
{
[SerializeField] TouchScreenKeyboardType keyboardType;
[SerializeField] TMP_InputField inputField;
void Reset()
{
inputField = GetComponent<TMP_InputField>();
}
public void OnSelect(BaseEventData eventData)
{
StartCoroutine(UnFocusByDefault());
}
IEnumerator UnFocusByDefault()
{
yield return new WaitForEndOfFrame();
inputField.DeactivateInputField();
}
public void OnSubmit(BaseEventData eventData)
{
TouchScreenKeyboard.Open(inputField.text, keyboardType);
}
}
I also added OnSubmit to open up the OS virtual keyboard because if you do it with OnSelect it fails to edit the input because we deselect it the next frame
If a controller (Xbox, PlayStation) is used then it seems that there is no way to exit the textfield once entered. The culprit seems to be that the “Submit” input actions is nit recognized (only the ENTER key on the keyboard is). I have extended it a bit to support controllers better. Sadly I had to use Update() for this.
I’ve also added auto detection for the Input so now you don’t have to drag it in anymore. And I have added a RequireComponent attribute since ISelectHandler, ISubmitHandler would only work if the script is directly attached to the TMP gameobject.
[RequireComponent(typeof(TMP_InputField))]
public class TMPInputFocusHelper : MonoBehaviour, ISelectHandler, ISubmitHandler
{
[SerializeField]
TouchScreenKeyboardType keyboardType = TouchScreenKeyboardType.Default;
protected TMP_InputField inputTf;
public TMP_InputField InputTf
{
get
{
if (inputTf == null)
{
inputTf = this.GetComponent<TMP_InputField>();
}
return inputTf;
}
}
public void OnSelect(BaseEventData eventData)
{
StartCoroutine(UnFocusByDefault());
}
IEnumerator UnFocusByDefault()
{
yield return new WaitForEndOfFrame();
InputTf.DeactivateInputField();
}
public void OnSubmit(BaseEventData eventData)
{
TouchScreenKeyboard.Open(InputTf.text, keyboardType);
}
public void Update()
{
// Sadly while entering text the "Submit" action does not
// end the input if done with a controller (keyboard ENTER
// works just fine).
// Catch Submit directly and end editing
if (Input.GetButtonDown("Submit") && InputTf.isFocused)
{
if (InputTf.isFocused
&& !Input.GetKeyDown(KeyCode.Return)
&& !Input.GetKeyDown(KeyCode.KeypadEnter))
{
InputTf.DeactivateInputField();
}
}
}
}