- Home /
How to bold only the selected characters from a text?
Hi all!
I am making an educational game for children where they need to bold names from a paragraph of story-type text.
So far I have figured out a way to bold the selected characters but it has some issues. I use TextMeshPro Input Field with Read Only and Rich Text enabled, so the characters can be selected by highlighting. I wrote a script that adds < b> and < /b> tags around the selected text when a key is pressed. To detect the position where to insert them I used TMP_TextUtilities.FindNearestCharacter which works quite well.
The problem however is that when I keep bolding the words from the text, the index number of characters change as the bolding tags are calculated as well. The FindNearestCharacter method doesn't seem to count the tags though, so after a while the bolding has offset. I tried to counter this by creating a calculation that would take the increase in characters into account but it works only for some time. At some point the offset appears.
Another problem occurs in the case if the selected characters are already bold. Instead of adding extra tags there I would need to remove the existing tags if I want to unbold the characters.
So I am asking is there any other way to bold the selected text than to add HTML tags? It is enough if the text appears to be bold even though in reality it is not.
My coding level is somewhere between beginner and intermediate, so I am quite clueless how to continue from this or is it even possible with the UI text.
Answer by Hans_Skroeber · Sep 06, 2019 at 08:28 PM
Allright, I found a solution!
I scrapped the use of FindNearestCharacter and instead found out that Input Field TMP stores data of the highlight box. I used inputFieldVariable.selectionStringAnchorPosition and selectionStringFocusPosition. They track the position of the highlight box's left and right edge (instead of coordinates they use the int value of the character which is at the same position) and take the bold tags into account when calculating index numbers unlike FindNearestCharacter.
Then I just used text.Insert to add the tags, text.IndexOf and LastIndexOf to search if there are tags existing, and then I removed them with text.Remove. Also I wrote lots and lots of if statements for different cases of inserting or removing the tags. Now the bolding and unbolding work well.Hi, after several hours of researches I've arrived to the same solution. I'm using selectionStringAnchorPosition and selectionStringAnchorPosition (tip for the readers: you need to check which one is greater to make inserts) and now I should write the logic to handle all the cases to apply a style to the selected text. Would you $$anonymous$$d to share your code on this topic? Thanks
By the way: it's crazy that a developer has to handle this simple and basic functions for his own.
Answer by s_awali · Sep 02, 2019 at 02:07 PM
As far as I know, there is no other way to bold part of a text of the same Text component.
However, you could try to use one Text component for each word, and wrap all those Text component inside a horizontal layer. That way, each word would have its own Text component, and therefore its own "OnClick" callback. You could then change the bold attribute of the Text component, and notify your game logic about this word being selected/unselected.
Don't know what the perfs would be tho', but I think it won't be that bad.
If you have trouble setting up this logic, keep me updated ;)
Thanks for the reply!
Yeah, it seems this would be the only option that would guarantee a nicely working bolding mechanism. Only drawback is that the individual letters can't anymore be highlighted and bolded. I would prefer to keep this mechanic in the game. The idea is to $$anonymous$$ch kids to use mouse and keyboard and to learn basic text editing skills through games. ($$anonymous$$y bad, I didn't specify this in detail in the post).
I need to think whether or not to sacrifice this ability. Looks like there is no way around it though.
If you want to keep your base idea you could use 2 Text components, one with the original text without the bold parts and set it invisible, the second one with the formated text that is visible. You could then use FindNearestCharacter on the invisible one (the one without the tags in it), and apply the modification to the visible one. You might still have some offset due to bold character taking a little more space tho.
Let me know if this workaround worked :)
Answer by Casiell · Sep 05, 2019 at 06:05 PM
Wait, am I not getting something, or you could just use string.Replace method?
Let's say you pressed 'N' so you do text = text.Replace("n", "n")
As for "unbolding" you can keep a list of bolded characters and then do the opposite replace on the text string.
I found a solution now! I didn't use text.Replace, but somehow a light bulb was switched on in my head when you mentioned about keeping a list of bolded characters. I didn't do that either actually but your comment encouraged me to still try with HT$$anonymous$$L tags and then little by little I got a solution to this! Thank you for inspiration! :D