How to identify which letter of a Label/TextElement is clicked on? Ie. To make a custom TextField?

I very much need the TextField element (or something like it) for my Mobile Android/iOS app which features SMS style texting, etc. There are three main problems I am encountering with the TextField and I’m therefore wondering about building my own custom class to make my own text field.

For reference, I am doing all my design in C#, so I don’t mind making derived classes or doing customization of some kind to make solutions work. I’m open to any ideas. I need a solution above all else.

1) Need to Remove Grey Border
The first problem is the simplest. The hierarchy for the TextField is as follows:

The object I have highlighted has a 1 pixel grey border around it which I need to remove. If I am coding, as in: TextField textField = new TextField();, what could I write in C# next to get rid of this grey border or manipulate the style of this component of it? Or is it not possible in C# to do so?

2) Need to Add Placeholder Text
I would like some way to have something show up in the text field like “Type a Message” as a placeholder that only shows up when the entry is empty and with a different text style than when there is something written. I don’t think these accept Placeholders, do they?

3) Need Resizing on Demand
Standard text input fields also will resize on demand, meaning they start a certain height and as more lines are added, up to a certain point they will resize in height. I could code something to monitor the geometry of the text label/field and increase the scrollview height to compensate up to a certain point, but I suspect I don’t have access to the internal workings in this case to do it, so again I’d have to code my own solution from the start.

SOLUTION?: BUILDING MY OWN TEXT FIELD
I suspect there is no good solution for these issues except custom coding my own TextField, which I am quite okay with doing. I have already built my own Buttons and Scrollviews by deriving from and customizing VisualElement to suit my needs.

The only base class I know that handles text is the Label class. My thought is at the simplest, I could:

  • Make a Label derived class and set it up so when you click on it, it opens the on screen keyboard.
  • Somehow I need to identify exactly what letter in the label you clicked (how could I do this?) so I can put a caret VisualElement there and note that is the point in the existing text from which to edit.
  • Update the label from TouchScreenKeyboard.text on a frame by frame basis.

If this is reasonable, I only need to know how to do one thing really:

How would I identify which letter of the Label is clicked to know where to put my caret upon starting editing?

I can easily use the Pick function to identify when the label is clicked, but I don’t know how to get the specific character/vertex that is clicked on.

How to find the characters you click on is explained in detail in the old UI system here, but I think this doesn’t help in UI Toolkit where I’m not sure how it works: Finding what letter/word I clicked

Any thoughts or solutions?

1 Like

Hi @mikemohan !

I don’t see the need to build a custom TextField to solve the issues you pointed out. Let me explain some workaround for each of them.

1- Override Default Styles: Please have a look at this thread . This is easier to do through USS, but it could also be done in C# by adding / removing USS class name. Any particular reason why you want to do this in C# rather than in USS?

2- Placeholder: This is a missing feature we already track internally and we definitely plan to add it at some point. In the meantime, you could implement your own placeholder. In the meantime, you’ll have to add the functionality yourself. This thread shows a few examples.

3- Layout: You should be able to achieve your desired behavior by using a mixt of min-height and max-height on the TextField. Let me know if you need more guidance.

As for interacting with the characters of the Text, these APIs are currently internal. In the future, we plan to introduce the tag to allow hooking the UITK event system with subsections of the text.

Hope this helps. Please, let us know if you face other blockers!

1 Like

Thanks for your helpful reply as always Hugo. You are right. It was very easy to to manipulate the style of the issue for #1 just by getting “TextField.Children()” and changing its style from there with code. #3 was also easy to solve - I did not see the min/max setting. It is good to know you are adding placeholder functions and I can look at those other temp solutions in the mean time.

The other problems I am having with the TextField are the following:

1) Unable to define when to close keyboard
I am having a hard time figuring out when/why the current TextField is set to close the on screen keyboard. If I click outside the TextField to some elements in my design (in very different parts of the UI hierarchy) it won’t close, but if I click again on it directly or on something very close in the hierarchy like the parent window box it closes.

I don’t know what is actually determining the behavior or whether it’s behaving as intended or not. Either way, is there any way to disable whatever logic has been applied for closing the keyboard with the TextField so I can control it myself?

The issue is if you have a basic text entry system like this, as in Android or really any modern app/system:

8025110--1033853--Screenshot_20220406-075017_Messages.jpg
You will have the space divided into two zones. The blue box is the “TextField” equivalent with a scroll window. The right red box is still part of what should be the “safe zone”, as clicks here should not close the keyboard. If you test on your own phone, you’ll find as any user would expect, clicking the dead space above the submit button does not close your keyboard. Furthermore, clicking the send button only closes the keyboard once it is released, not on initial clicking.

Currently, if I rig up something similar, once the keyboard is open, clicking again on the textfield, or in the right red dead space, or on the submit button all close the keyboard (which also causes the send button to malfunction as it immediately moves and defocuses).

Am I missing something? If not, if you can give us a function to disable the text field from closing the keyboard, we can just define whenever we want it to close. Then if someone wants to close it manually based on their own rules (the three common conditions would be pressing “back” button or “escape” or upon proper in bounds click and release of the “submit” button) they can code that on their own.

2) TextField not scrolling or accepting mid point editing on Android and no Caret/Scrollbar showing up
When I run a text field in Unity Editor, it automatically scrolls as I type new inputs onto new lines. I can also click with my mouse part way through the text and add new text mid way via keyboard. However, when I use it in Android it does not scroll automatically (the new text goes off the bottom of the view port and I must manually scroll down to see it).

Both in Unity Editor and Android there is also no caret or scrollbar showing up. Is this normal as well? I tried setting a cursor image with numerous images but nothing shows up as a caret in Editor or Android.

Lastly in Android I cannot click part way through the input field and reposition the editing or new text entry point.

Hopefully I am just missing something again for all of this. For the record, I am using TouchScreenKeyboard.hideInput = true; as this is necessary for my visual function.

Thanks again for your help.

Hi @mikejm ,

  • Thank you for bringing this up, and upon having a quick look, you are not missing anything. The soft keyboard, as of now, would only close if another soft keyboard instance has been detected, but then it will promptly open a new one. Additionally clicking in the “Ok” or “Done” will also set the keyboard off. There were a pair of fixes we did recently which addresses some inconsistent behaviors with the focus and blur (focus out) events, the keyboard will open and close according to the events (focus in and focus out). Most importantly, we will take your use case back and see what we can do to in order to make it easier for users to control the soft keyboard’s behavior, specially when it involves a more complex layout tied with different types of interactivity.
  • As of now, the in place editing is not fully supported, hence why disabling the OS input will have some missing features. Good new is, we added support for in place editing to the Input fields which should be coming along with other improvements and which is set to land in 2022.2.
1 Like

Thanks Freddy. It sounds like then you will be fixing the Android/iOS in place editing to allow it to scroll properly and to allow midpoint editing for 2022.2. That is very helpful. (I am currently using 2022.1.0b14 for reference.)

Will you also be adding the caret/cursor support so users can see where they are clicking or editing? What about line wrapping? Currently lines are not wrapping in multiline automatically.

These are all really important functions for replicating simple texting functions like users expect from Android/iPhone/Whatsapp/SnapChat/etc. If we aren’t permitted access to figuring out where each letter is (so we can’t make our own input fields), then I would hope any provided input field should be able to let us do something like that. Personally at least, I very much do need it. I would even be willing to pay you guys something extra to get it functioning to this level if needed as I’m dependent. Or pay for access to figuring out where each letter in a label is so I can make something with these minimal basic functions myself.

In terms of closing the keyboard, I am not sure what the problem is or whether what I am seeing happening is normal or not. I would be happy if it never closes on its own. Ideally, if you can give us a function to disable the automatic closing and then close it on demand ourselves that would be perfect.

TextField Test Environment:
To illustrate what I am seeing, here is a mockup I programmed of an SMS style chat window:

8030789--1035299--Screenshot_20220408-062326_My project 2.jpg

The red box outlines the perimeter of the TextField. The blue zone is a custom made scrollview made from a click-drag-translatable VisualElement derived class holding some dummy text messages. The green is a “submit” button which was also made from a VisualElement derived class that has some basic click detection and run functions.

While the keyboard is open:

  • If I click on the blue zone to scroll the window the keyboard does not close (in Android built in SMS function, scrolling the text window does close it).
  • Clicking anywhere in the red zone (the TextField) instantly closes the keyboard (which is obviously not correct but I presume may be due to the lack of working “in place editing” as you say that will be fixed?).
  • Clicking the grey “submit” button also closes it instantly, thus making it impossible for the click to even register unless I make it take the “submit” signal on immediate mousedown rather than on mouseup (which is again abnormal - a “submit” button of this nature should not do anything until it’s released while still over the button).

What’s strange to me is why clicking and scrolling in the blue window doesn’t close it but clicking on the field itself or the button next to it does.

Is it running TextField.Blur() when I press some areas of the screen and not others? Does it maybe have something to do with the PickingMode for the VisualElement perhaps whether this runs or not? I tested my submit VisualElement and it has focusable set to false by default. So why would clicking it defocus/blur the TextField? Why does clicking the scrollview I made NOT defocus/blur the TextField when they are both just basic VisualElement derived classes?

Is there any way I can debug something out to figure out what is happening and what is triggering the closures?

Proposed Solution:
The ideal solution to this I think would be to (1) allow a switch for us to “deactivate automatic blur/defocus events” (whatever it is that is happening), (2) give us a function like UI.InputField.DeactivateInputField so we can close it manually if we want (or if TextField.Blur() does this already no need), and (3) have a simple bool to check also if a given TextField is “activated” or “focussed” at any given time.

Then for someone like me building an SMS style texting function, I could disable the automatic closing, and in my click management functions, I can add the manual close keyboard function (blur?) at the end of my “Submit” button custom function so it only runs the close function once that’s done. If I can detect the TextField as “activated,” I can also add the close command for clicks that I detect outside the TextField’s or Submit button’s bounds, so clicking in the scrollview or other UI would close it also.

So if it’s the “Defocus” event that is closing it in my mockup described above, then, to reiterate, I propose:

  • Adding a function or bool to accomplish “DisableDefocusEvents” (from wherever they are being triggered).

  • Adding a function to close it manually like “DeactivateTextField” (if “Blur” does this already no need).

  • Giving us a bool like “isTextFieldActive”.

Would that be difficult to do? I imagine it wouldn’t be too difficult on your end. It would give us total flexibility to monitor and close the TextField any time we want under our own conditions.

To me that sounds pretty ideal, likely simple for you, and broadly flexible for everyone. It should allow us to build basically anything we want including these types of text/chat functions without likely any major extra work on your end. What do you think? Is that reasonable or doable?

The only time I would want the TextField to lose focus automatically is if there are two TextFields on screen and you click from one to the other - then obviously it should trade focus automatically.

Beyond that, it’s hard for me to say in more depth how it should work as I don’t understand why it’s closing as it is now in the first place. Hopefully that gives you some impression for what would be needed for this type of necessary basic text input function to work. Perhaps if you can explain more about why I’m seeing the behavior I described above I can be more precise.

Thanks for your consideration and any further thoughts.