Important Message Related to the TextField Refactor for 2022.1+.

An important refactor has landed in 2022.1.0a15. It provides a TextField that fully relies on TextCore for both the Editor and Runtime, removing UI Toolkit’s dependency on Native Text, the legacy text system, and getting us a step closer to feature parity with TextMeshPro. However, some important changes had to be done to the inside components of TextFields introducing behavior changes that might have a significant impact on existing code.

New Features:

  • TextFields can now display a vertical scrollbar. Whereas before achieving the same result would have required doing some delicate manipulations of the inside of a TextField. It can now easily be achieved by updating the scrollbar visibility.

  • inputField.SetVerticalScrollerVisibility(ScrollerVisibility.Auto);7671553--958270--showScrollbars.gif

  • All the logic related to rendering, selecting and editing text is now all gathered in TextElement. This refactor gave the capabilities to every TextElements of being selectable. Whereas before achieving the same result would have required the usage of a custom TextField disguise as a label. It can now easily be achieved by setting isSelectable.

  • textElement.selection.isSelectable = true;7671553--958273--selectable.gif

  • TextCore text assets (FontAssets, SpriteAssets, PanelTextSettings, ColorGradient and TextStyleSheet ) are now supported inside TextFields. It means TextFields now leverage the benefits of SDF rendering, getting UI Toolkit a step closer to feature parity with TextMesh Pro.

  • Based on your feedback, we have improved the selection API by providing more control to all TextElements and TextFields:

  • cursorColor

  • selectionColor

  • cursorPosition

  • cursorIndex

  • selectIndex

  • doubleClickSelectsWord

  • tripleClickSelectsLine

  • HasSelection

  • SelectAll

  • SelectNone

  • SelectRange

What changed:

The TextField internal hierarchy has changed. While ideally, this should be an implementation detail, some new physical VisualElements are now existing under the Field. Now all logic related to rendering, selecting, and editing has been centralized inside TextElement, which is a new child of TextFields. This improves maintainability, reduces duplication, and provides more capabilities to all TextElements such as selecting. Moreover, to have a more intuitive API, both TextFields and TextElements now implement the same selection API. Therefore, the inner hierarchy of TextFields went from this:

To this for singleline TextField

To this for multiline TextField

To this, if the ScrollView is set to visible:

Behavior change:

  • Due to the inner hierarchy of TextFields changing, broad queries that relied on a specific hierarchy order or select internal components might be broken.

Examples of such queries that may be affected:

  • Accessing an inner component of the TextField through its hierarchy placement:

  • var innerComponent = field.hierarchy[index];

  • Since TextFields now have a ScrollView and a TextElement as children, queries that fetch the first ScrollView or the first TextElement encountered without specifying a classname or name might be affected:

  • var scrollView = root.Q<ScrollView>();

  • var textElement = root.Q<TextElement>();

  • Since the leaf element of the TextFields has changed from TextInputBase to TextElement, some RegisterCallback on TextInputBase that relied on being invoked before ExecuteDefaultActionAtTarget() might be invalid. In other words, it affects RegisterCallback on inner components of the TextFields that intercepted events before they arrived at target. For more information, please refer to the documentation for the dispatching of events and event handling.

  • Example of a RegisterCallback that intercepted the KeydownEvent before it gets to ExecuteDefaultActionAtTarget():

  • field.Q("unity-text-input").RegisterCallback<KeydownEvent>(OnKeyDownEvent);

  • To achieve the same result as before, you will need to register on the TrickleDown phase of the Event propagation loop like so:

  • field.RegisterCallback<KeydownEvent>(OnKeyDownEvent, TrickleDown.TrickleDown);

We will continue to improve the TextField throughout the 2022.2 release cycle with the end goal of getting to feature parity with TextMeshPro.

20 Likes

Thank you for bringing UIToolkit one step closer,
TMPro Input Field have limitations on mobile, so please along with feature parity also take care of solving those limitations so we can have better player chat in our mobile game due to improved input field that provide text selection, mobile native auto correct, and “ideally” a visual rich text editor

1 Like

Thanks, @jGate99 for taking the time to provide feedback! Improving the soft keyboard along with rich text are our next areas of focus.

3 Likes

Is there any chance this will make it back into 2021LTS? If there’s one thing I need fixed it is the TextField and I was really hoping there’d be an answer 2021.2.

Hi @Arkenhammer !

Unfortunately, this will not be backported, mostly due to the size of this refactor and the risk of introducing new regressions.

Could you be more specific on what you hope would be fixed in the TextField, while we can’t backport the whole refactor, we might be able to backport some of the fixes.

I have a bunch of needs from it but the big one is to be able to edit field focus in code.
I need a text field which only gets focus when the player clicks on it and always loses focus when the player confirms they are done editing.
The current text field grabs focus whenever a character is typed. Unfortunately that means it grabs focus when, for instance, the player is navigating the world with the WASD keys and the field gets filled with gibberish. The way I attempt to handle this is to disable the text field when its not in “edit mode” and then enable & focus it on a click. However the focus doesn’t take and currently it takes two clicks to actually enter text–the first when enables the text field and the second which focuses it.

While I am adding wishes–I layout my screen using a larger coordinate system than the screen and set the “Panel Settings” to scale it to match the screen. However the text field uses a single point wide rectangle for the vertical bar and, when scaling, that regularly aliases down to zero pixels and vanishes.

I was hoping that the TextField was going to be stable in 2021LTS, but now it looks like its 2022 which is too far out for me. Currently I am contemplating writing my own or else grabbing the code out of the package and forking it so I can make something that works for me. Is going to be any way to positively control TextField focus in 2021 or am I on my own for this?

1 Like

Hi @Arkenhammer !

This should be supported in 2021.2. You could do it like so:

textField.Focus();
textField.Blur();

This issue hasn’t been fixed by the refactore. In fact, the issue you are observing is due to the fact that the InputSystem sends navigation events when “WASD” is typed. There are multiple ways of fixing this. If you have the UGUI EventSystem, simply disabling “Send Navigation Events” will do the trick. However, NavigationEvents will no longer be sent. An other alternative is to add a RegisterCallback to your fields and stop the NavigationEvents like so:

Are you referring to the carret width here ? If so, I beleive the issue is still present in the latest version. Could you log a bug though the unity bug reporter (Help/Report a bug…) ? This will help us with visibility and to make sure it is backported.

1 Like

While I love that the text development is continuing, I can’t say I’m glad about the inclusion of the scrollbar/scrollview in the textfield.

This very thing causes me lots of issues with the original tmpro, as the text is then also responsible for scrolling and makes a bunch of assumptions about how and when that should work. It makes every use case but the standard one more difficult and also complicates nesting tmpro_inputfields in scrollviews. Want text with horizontal scroll only? Want scrolling that syncs with input? Want selection but no scrolling? Want a different start point for the scroll bar or a different scroll direction? Want to manipulate the scrollpoint in some way? Want to disable scrolling in certain situations? All these things and more become more complicated and you have to learn several ways to solve them. Want to configure a scrollbar for some text element? Your normal scrollbar knowledge is no good, better learn how to access the scrollbar through the text element, investigate the source code to find out how tmpro wants the scrollbar to be used and when it accesses/changes its properties. Also be prepared to fight or fork tmpro elements if you have anything planned that doesn’t align with its vision of scrolling.

=> Scrolling content and rendering text are two different concerns, so I’m not convinced it is wise to have the text rendering element have strong opinions/knowledge/dependencies about how it is scrolled. I hope this separation will be cleaner here than it is in the original tmpro.

Another point, since font assets were mentioned. I would be amazing if tmpro could also give us a cleaner cut in terms of generated and static assets. Having assets be half generated and half static (I’m looking at dynamic font atlas features in particular) frequently causes small, but entirely avoidable mistakes (mostly to do with versioning).

4 Likes

Hi @leutnant_kane !

Thanks a lot for sharing your thoughts. I’m not too familiar with how texfield + scrollview works in TMP and so I can’t comment on its usability, but I can talk about UIToolkit’s TextField.

First, here’s an update on the state of things. We are currently working on only adding the inner ScrollView when users change the Scrollbar visibility. In other words, the default TextField (multiline and singleline) will use a custom scrolling mechanism to handle the offset when the text overflows. The main purpose of this change is to improve the performance of instantiation, as the ScrollView is a heavy control. It should also allow users who want to embed a TextField into their own ScrollView and configure it as they see fit to do so. That being said, I believe there are better alternatives to achieve the same results.

While it’s true the currently exposed properties don’t offer the flexibility you are looking for, APIs will be added to the TextField to allow it to acheive most of what you mentioned above. In fact, it should be fairly easy to do so as the underlying ScrollView used by the TextField is the same one as the one provided by the framework and everything you mentioned above is already supported by the native ScrollView.

I can’t recommend you to do this, but as a temporary workaround, you could query the inner ScrollView (like so: innerScrollView = textField.Q()) and configure it as you see fit.

Hi @HugoBD-Unity ,
Thank you for your quick response :slight_smile:

A quick and dirty overview of the way tmpro does it:
The inputfield itself does the scrolling/hides its scrolling parts from the outside. You can set a vertical scrollbar and do some configuration, but the component itself has a strong/hardcoded opinion about how that scrollbar is used/how it wants to be scrolled. So if your use case doesn’t exactly align with that, be prepared to dive into that tmpro source code (to either modify it or time your edits right after tmpro does them, which is sketchy at best).

The scrollview itself being queryable does help I think. Still I am sceptical about a couple of points here:

  • Yes the current (and the original tmpro) textfield properties do not allow for the flexibility I’m looking for, but as you’ve said the native scrollview supports all that. I’m not advocating putting all scrollview properties into the textfield, I’m advocating putting none of them in there (not even the scrollview itself), because I’m not convinced the textfield should care about how it is scrolled at all.

  • Why put this at the textfield level? Why would a textfield have the ability to be scrolled, but a textlabel does not? Why wire the ability to get scrolled into one kind of text object. Why wire it into any specific object at all? Why should a textfield be scrolled differently than a textlabel or any other object?

  • As far as I’m concerned a Textlabel just renders text in a container (and allows read interactions: select text, copy, etc.). A textfield extends this to allow write interactions (and placeholders). A Masking component limits rendering of a container to its region and a Scrolling component decides where on the container an object (the masking region in this case) resides. I don’t see much reason for hard coding/intimately wiring all of these parts together (except maybe performance considerations, but even then I’m not convinced the text component should have opinions/set things like scroll direction etc.).

  • In your post you point out that you believe there are better ways to achieve modularity/flexibility than embedding a textfield into a scrollview. I am curious what you had in mind here? Writing custom text components to change things like scroll direction does not seem very modular/flexible to me.

Thanks for reading through my questions/concerns :slight_smile:

2 Likes

Adding the scrolling capabilities requires advanced programming skills as there are many edge cases to consider. Forcing all users to implement their own scrolling doesn’t seem like a reasonable option to me. I would expect TextFields to scroll automatically to follow the caret position.

To implement all the scrolling capabilities, the ScrollView needs to have intimate knowledge of the TextField (each line-height, each line-width, caret position, multiline…).

On the other hand, you are right, while we offer default scrolling capabilities for TextFields, we should also allow users who want to embed their TextField into their own ScrollView to be able to do so. We’ll add a way to disable scrolling in the TextField.

1 Like

Hi @HugoBD-Unity
We just lost Advanced TextInput Field 2 for uGUI, so my question is, is UI Toolkit based Text Input works on mobile with caret selection and features such as auto suggest / auto fill?
If not, any plans for that?

Hi @jGate99 , we plan to improve our mobile soft keyboard for 2022.2. We aim at feature parity with the TextMesh Pro mobile InputField.

2 Likes

I dont think feature parity alone will solve it, we atleast need 2 things in mobile input field
1- caret selection or ability to tap and any where in text and change it rather than deleting whole text
2- auto suggest/remember feature

So please please please, consider this

1 Like

Hi @jGate99 ! We took note of your request. Thanks a lot for your feedback and don’t hesitate if you see other missing features. We see the importance of the features you highlighted above, but I can’t say when we’ll tackle those yet!

1 Like

If I want to focus to the TextField in code, I’d expect that I could call textField.Focus(). It seems to get the focus (the border color of the input field changes, in the editor a cursor appears) but when I build this to my mobile device no keyboard is shown!

This is a real problem and a regression from the old TextField which worked as expected and which we are wrapping in a custom component and call focus from there.

To add a question:

  1. Is this a bug or the new intended behavior?
  2. Is there a way to manually force showing and/or hiding the soft keyboard on Android/iOS?
2 Likes

Hi @seyfe , thank you for bringing this issue up with us! After taking a quick peek at this, I can confirm it is a regression - we will look into fixing this as soon as possible. To answer your questions:

  • It’s a bug
  • Unfortunately, there is no way to manually force open the soft keyboard on Android/iOS at the moment

Thanks, @FreddyC-Unity , for the answer! What about closing the soft keyboard? :wink:

@seyfe , we are working on a series of soft keyboard improvements for the text field and this too will be included with it :).

2 Likes

@HugoBD-Unity Can I scroll to last position by using script? I’m trying to implement console-log like UI which shows latest message automatically, but I can’t find the way.