Search Unity

TextMesh Pro Linked Text in UGUI Layout Groups

Discussion in 'UGUI & TextMesh Pro' started by Alchemy_Fire, May 17, 2017.

  1. Alchemy_Fire

    Alchemy_Fire

    Joined:
    Aug 27, 2013
    Posts:
    14
    Hi,

    I have a UI control that displays text and images inside a scroll rect. The text and images are organised as a gameobject per paragraph / image and are under the control of a vertical layout group / combo size fitter on the scroll rect content panel.

    The content is dynamic.

    I'm trying to add a dropcap to the first paragraph. To do this I create a normal UGUI text component for the drop cap and a TMP UGUI component for the text that border the drop cap to the right. These two objects share a common parent that has a layout element with a height equal to that of the dropcap (see pic: #1). I then create another object with a TMP UGUI component and I set the first component overflow mode to 'Linked' and point it at the second component (#2).

    This works BUT the second TMP UGUI is too large. I think it's calculating its size based on the text of the original source component. If I add another non linked object with TMP UGUI component then it sizes its self correctly (#3).

    Am I doing something wrong or is this just a limitation of linked overflow mode? If it is a limitation, any ideas on how to implement drop caps with dynamic text in a layout group?

    DropCap_Issue.png
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    It is likely using the size from the source text.

    Can you provide me with a simple Repro scene that I can use for testing. Make sure the exported package only includes the scene and potential dependency like an image. Ie. don't include all of TextMesh Pro :)

    As soon as I have a chance, I'll take a look at it.

    Here is an alternative way to do drop cap. http://digitalnativestudios.com/forum/index.php?topic=582.msg6840#msg6840
     
  3. Alchemy_Fire

    Alchemy_Fire

    Joined:
    Aug 27, 2013
    Posts:
    14
    Thanks Stephan, appreciate the reply.

    Attached is very minimal repo.

    Unfortunately this won't work in my case because the text is dynamic so I need a way to work out where to stop the indentation. Fortunately I was able to cobble something together by forcing a layout update and then using firstOverflowCharacterIndex on TMP_Text to do the linking myself. In case this helps anyone I have included some sample code and example gif below.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using TMPro;
    4.  
    5.  
    6. [ExecuteInEditMode]
    7. public class DropCapParagraph : MonoBehaviour
    8. {
    9.     public Text DropCap;
    10.     public TextMeshProUGUI RightText;
    11.     public TextMeshProUGUI BelowText;
    12.     [TextArea(5, 3), SerializeField] private string paragraph;
    13.    
    14.     private char dropCapChar;
    15.     private string textStr;
    16.  
    17.     private bool valid
    18.     {
    19.         get { return paragraph != null && paragraph.Length > 0 && DropCap && RightText && BelowText; }
    20.     }
    21.  
    22.     public string Paragraph
    23.     {
    24.         get { return paragraph; }
    25.         set {
    26.             paragraph = value;
    27.             distributeParagraphText();
    28.         }
    29.     }
    30.  
    31.     // Check to see if the RightText component is overflowing - if so split the text between RightText and BelowText based on the
    32.     // overflow charadcter index.
    33.     private void distributeParagraphText()
    34.     {
    35.         if (!valid)
    36.             return;
    37.  
    38.         // Assign the 1st char of paragraph to the dropcap component and the rest of the paragraph to the 'RightText' component.
    39.         dropCapChar = paragraph.ToCharArray()[0];
    40.         DropCap.text = dropCapChar.ToString();
    41.         textStr = paragraph.Substring(1, paragraph.Length - 1);
    42.         RightText.text = textStr;
    43.  
    44.         // This call causes the RightText TextMeshProUGUI component to do some form of layout which make 'isTextOverflowing' /
    45.         // 'firstOverflowCharacterIndex' consistent with the text assigned above.
    46.         RightText.Rebuild(CanvasUpdate.PreRender);
    47.  
    48.         if (RightText.isTextOverflowing)
    49.         {
    50.             var txt = RightText.text;
    51.             var idx = RightText.firstOverflowCharacterIndex;
    52.             RightText.text = txt.Substring(0, idx - 1);
    53.             BelowText.text = idx >= txt.Length ? "" : txt.Substring(idx);
    54.         }
    55.         else
    56.             BelowText.text = "";
    57.     }
    58.  
    59.     private void OnEnable()
    60.     {
    61.         if (valid)
    62.         {
    63.             // RightText needs to be in Overflow mode for 'isTextOverflowing' / 'firstOverflowCharacterIndex' to work.
    64.             RightText.overflowMode = TextOverflowModes.Overflow;
    65.             BelowText.overflowMode = TextOverflowModes.Overflow;
    66.             distributeParagraphText();
    67.         }
    68.     }
    69.  
    70.     private void Start ()
    71.     {
    72.         distributeParagraphText();
    73.     }
    74.  
    75.     private void OnValidate()
    76.     {
    77.         distributeParagraphText();
    78.     }
    79. }
    80.  
    DropCap_Example_Working.gif
     

    Attached Files:

  4. RobBrooks

    RobBrooks

    Joined:
    Oct 15, 2013
    Posts:
    5
    Exactly this problem.
    Many thanks for the fix.
     
  5. bluefairymediallc

    bluefairymediallc

    Joined:
    Dec 10, 2019
    Posts:
    10
    Same issue for me, except the second textbox gets its height set to 0 instead of being too large. Not always, though--it seems to depend on the actual text. It wraps nicely for four to five blocks of lorem ipsum but not for my dynamically populated text where paragraph size varies.

    I'll have to try Alchemy_Fire's solution later.