Search Unity

TextMesh Pro Does the Content Size Fitter work?

Discussion in 'Unity UI (uGUI) & TextMesh Pro' started by BlockFade, Jul 23, 2017.

  1. BlockFade

    BlockFade

    Joined:
    Jan 28, 2017
    Posts:
    24
    I'm making a dialogue bubble where it will automatically resize the bubble to the text's size.

    I have the content size fitter attached to the background image.

    But if the Text overflows, the background image doesn't change size!

    Does the content size fitter not work with TextMesh Pro?
     
  2. HonorableDaniel

    HonorableDaniel

    Joined:
    Feb 28, 2007
    Posts:
    2,830
    Try setting the vertical fit to preferred size. Unconstrained does nothing.
     
  3. BlockFade

    BlockFade

    Joined:
    Jan 28, 2017
    Posts:
    24
    It did this...
     
  4. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,348
    The Content Size Fitter does work but you have to make sure you are using the TextMeshPro UGUI Component which is located in Create - UI - TextMeshPro - Text
     
  5. BlockFade

    BlockFade

    Joined:
    Jan 28, 2017
    Posts:
    24
    It is using TextMeshPro UGUI:
     
  6. MrHappyKiller

    MrHappyKiller

    Joined:
    Feb 8, 2016
    Posts:
    29
    If your content size fitter is not connected to your speech bubble sprite, it will not expand your speech bubble; only the text box.
     
  7. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,348
    You have to add some Layout component like Horizontal or Vertical Layout Group.

    upload_2017-7-22_20-14-56.png
     
    SpyDev, wuhuan and MrMatthias like this.
  8. BlockFade

    BlockFade

    Joined:
    Jan 28, 2017
    Posts:
    24
    Thank you for your help!
    I got it working :)
     
  9. nrvllrgrs

    nrvllrgrs

    Joined:
    Jan 12, 2010
    Posts:
    12
    I'm using the same settings but my panel expands the full height of the canvas. Below are the behaviors when I change my vertical fit:
    • Unconstrained: No change
    • Min Size: Panel's height (and child TextMeshPro UGUI height) set to 0
    • Preferred Size: Panel's height (and child TextMeshPro UGUI height) set to canvas height
     
    Nodata likes this.
  10. Nodata

    Nodata

    Joined:
    Oct 29, 2014
    Posts:
    1
    Same is happening to me. Is this broken now?
     
  11. warreneng

    warreneng

    Joined:
    Mar 13, 2017
    Posts:
    8
    Sure seems like ContentSizeFitter is broken. I'm using 2018.2.12f
     
  12. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,348
    I don't recall adding a ContentSizeFitter alone on a parent object like a UI Button working. Adding either an HorizontalLayoutGroup or VerticalLayoutGroup still appears to work in addition to the ContentSizeFitter does still appear to work. See the example I posted above.
     
  13. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    1,261
    This may be overkill for a minor annoyance, but if you prefer, you could use this component:

    Code (CSharp):
    1. using UnityEngine;
    2. using TMPro;
    3.  
    4. // Resizes this object based on the preferred size of a TMP Text
    5. [ExecuteInEditMode]
    6. public class TextSizer : MonoBehaviour
    7. {
    8.     public TMP_Text text;
    9.     public Vector2 padding;
    10.     public Vector2 maxSize = new Vector2(1000, float.PositiveInfinity);
    11.     public Vector2 minSize;
    12.  
    13.     public enum Mode
    14.     {
    15.         None        = 0,
    16.         Horizontal  = 0x1,
    17.         Vertical    = 0x2,
    18.         Both        = Horizontal | Vertical
    19.     }
    20.     public Mode controlAxes = Mode.Both;
    21.  
    22.     protected string lastText = null;
    23.     protected Vector2 lastSize;
    24.     protected bool forceRefresh = false;
    25.  
    26.     protected virtual float MinX { get {
    27.             if ((controlAxes & Mode.Horizontal) != 0) return minSize.x;
    28.             return GetComponent<RectTransform>().rect.width - padding.x;
    29.         } }
    30.     protected virtual float MinY { get {
    31.             if ((controlAxes & Mode.Vertical) != 0) return minSize.y;
    32.             return GetComponent<RectTransform>().rect.height - padding.y;
    33.         } }
    34.     protected virtual float MaxX { get {
    35.             if ((controlAxes & Mode.Horizontal) != 0) return maxSize.x;
    36.             return GetComponent<RectTransform>().rect.width - padding.x;
    37.         } }
    38.     protected virtual float MaxY { get {
    39.             if ((controlAxes & Mode.Vertical) != 0) return maxSize.y;
    40.             return GetComponent<RectTransform>().rect.height - padding.y;
    41.         } }
    42.  
    43.     protected virtual void Update ()
    44.     {
    45.         RectTransform rt = GetComponent<RectTransform>();
    46.         if (text != null && (text.text != lastText || lastSize != rt.rect.size || forceRefresh))
    47.         {
    48.             lastText = text.text;
    49.             Vector2 preferredSize = text.GetPreferredValues(MaxX, MaxY);
    50.             preferredSize.x = Mathf.Clamp(preferredSize.x, MinX, MaxX);
    51.             preferredSize.y = Mathf.Clamp(preferredSize.y, MinY, MaxY);
    52.             preferredSize += padding;
    53.  
    54.             if ((controlAxes & Mode.Horizontal) != 0)
    55.             {
    56.                 rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, preferredSize.x);
    57.             }
    58.             if ((controlAxes & Mode.Vertical) != 0)
    59.             {
    60.                 rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, preferredSize.y);
    61.             }
    62.             lastSize = rt.rect.size;
    63.             forceRefresh = false;
    64.         }
    65.     }
    66.  
    67.     // Forces a size recalculation on next Update
    68.     public virtual void Refresh()
    69.     {
    70.         forceRefresh = true;
    71.     }
    72. }
     
    Akrone likes this.
  14. Akrone

    Akrone

    Joined:
    Jun 4, 2018
    Posts:
    2
    Actually this is the most viable solution I found, here's a bit more optimized version of @Antistone 's code, note that if you destroy the TMP component or change its reference at runtime you'll have to call Refresh()
    Code (CSharp):
    1.  
    2. [ExecuteInEditMode]
    3. public class TextSizer : MonoBehaviour
    4. {
    5.     public TMP_Text Text;
    6.     public bool ResizeTextObject = true;
    7.     public Vector2 Padding;
    8.     public Vector2 MaxSize = new Vector2(1000, float.PositiveInfinity);
    9.     public Vector2 MinSize;
    10.     public Mode ControlAxes = Mode.Both;
    11.    
    12.     [Flags]
    13.     public enum Mode
    14.     {
    15.         None        = 0,
    16.         Horizontal  = 0x1,
    17.         Vertical    = 0x2,
    18.         Both        = Horizontal | Vertical
    19.     }
    20.  
    21.     private string _lastText;
    22.     private Mode _lastControlAxes = Mode.None;
    23.     private Vector2 _lastSize;
    24.     private bool _forceRefresh;
    25.     private bool _isTextNull = true;
    26.     private RectTransform _textRectTransform;
    27.     private RectTransform _selfRectTransform;
    28.  
    29.     protected virtual float MinX { get {
    30.         if ((ControlAxes & Mode.Horizontal) != 0) return MinSize.x;
    31.         return _selfRectTransform.rect.width - Padding.x;
    32.     } }
    33.     protected virtual float MinY { get {
    34.         if ((ControlAxes & Mode.Vertical) != 0) return MinSize.y;
    35.         return _selfRectTransform.rect.height - Padding.y;
    36.     } }
    37.     protected virtual float MaxX { get {
    38.         if ((ControlAxes & Mode.Horizontal) != 0) return MaxSize.x;
    39.         return _selfRectTransform.rect.width - Padding.x;
    40.     } }
    41.     protected virtual float MaxY { get {
    42.         if ((ControlAxes & Mode.Vertical) != 0) return MaxSize.y;
    43.         return _selfRectTransform.rect.height - Padding.y;
    44.     } }
    45.  
    46.     protected virtual void Update ()
    47.     {
    48.         if (!_isTextNull && (Text.text != _lastText || _lastSize != _selfRectTransform.rect.size || _forceRefresh || ControlAxes != _lastControlAxes))
    49.         {
    50.             var preferredSize = Text.GetPreferredValues(MaxX, MaxY);
    51.             preferredSize.x = Mathf.Clamp(preferredSize.x, MinX, MaxX);
    52.             preferredSize.y = Mathf.Clamp(preferredSize.y, MinY, MaxY);
    53.             preferredSize += Padding;
    54.  
    55.             if ((ControlAxes & Mode.Horizontal) != 0)
    56.             {
    57.                 _selfRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, preferredSize.x);
    58.                 if (ResizeTextObject)
    59.                 {
    60.                     _textRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, preferredSize.x);
    61.                 }
    62.             }
    63.             if ((ControlAxes & Mode.Vertical) != 0)
    64.             {
    65.                 _selfRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, preferredSize.y);
    66.                 if (ResizeTextObject)
    67.                 {
    68.                     _textRectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, preferredSize.y);
    69.                 }
    70.             }
    71.            
    72.             _lastText = Text.text;
    73.             _lastSize = _selfRectTransform.rect.size;
    74.             _lastControlAxes = ControlAxes;
    75.             _forceRefresh = false;
    76.         }
    77.     }
    78.  
    79.     // Forces a size recalculation on next Update
    80.     public virtual void Refresh ()
    81.     {
    82.         _forceRefresh = true;
    83.        
    84.         _isTextNull = Text == null;
    85.         if (Text) _textRectTransform = Text.GetComponent<RectTransform>();
    86.         _selfRectTransform = GetComponent<RectTransform>();
    87.     }
    88.     private void OnValidate ()
    89.     {
    90.         Refresh();
    91.     }
    92. }
    93.  
    The object on which this component is attached get resized according to the place that the TMP object and optionally resizes it via ResizeTextObject
     
    Last edited: Jul 3, 2019
  15. RavenmoreArt

    RavenmoreArt

    Joined:
    Aug 28, 2014
    Posts:
    1
    Thanks for this! I just wanted to add that if you add/remove stuff from your menus dynamically its a good idea to add this to the code:

    Code (csharp):
    1.  
    2. public virtual void Start()
    3. {
    4.     Refresh();
    5. }
    6.  
    That makes sure the size is recalculated when the object is spawned.