Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by ZakisGrigoroudis · Oct 13, 2021 at 04:54 PM · texttoolkitfitbuilder

UI Toolkit - Text Best Fit

Is there a way to make the text fit the container (by automatically adjusting its font) using the new UI Toolkit and UI Builder?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by ZakisGrigoroudis · Oct 24, 2021 at 06:31 PM

Thank you @andrew-lukasik, I made a new script following your steps that seems to fit more properly to my needs. It is not perfect though as it doesn't refresh properly in a few cases. Any improvements are welcome.

 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UIElements;
 
 public class LabelAutoFit : Label
 {
     [UnityEngine.Scripting.Preserve]
     public new class UxmlFactory : UxmlFactory<LabelAutoFit, UxmlTraits> { }
 
     [UnityEngine.Scripting.Preserve]
     public new class UxmlTraits : Label.UxmlTraits
     {
         readonly UxmlIntAttributeDescription minFontSize = new UxmlIntAttributeDescription
         {
             name = "min-font-size",
             defaultValue = 10,
             restriction = new UxmlValueBounds {min = "1"}
         };
 
         readonly UxmlIntAttributeDescription maxFontSize = new UxmlIntAttributeDescription
         {
             name = "max-font-size",
             defaultValue = 200,
             restriction = new UxmlValueBounds {min = "1"}
         };
 
         public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription { get { yield break; } }
 
         public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
         {
             base.Init(ve, bag, cc);
 
             LabelAutoFit instance = ve as LabelAutoFit;
             instance.minFontSize = Mathf.Max(minFontSize.GetValueFromBag(bag, cc), 1);
             instance.maxFontSize = Mathf.Max(maxFontSize.GetValueFromBag(bag, cc), 1);
             instance.RegisterCallback<GeometryChangedEvent>(instance.OnGeometryChanged);
             instance.style.fontSize = 1; // Triggers OnGeometryChanged callback
         }
     }
 
     // Setting a limit of max text font refreshes from a single OnGeometryChanged to avoid repeating cycles in some extreme cases
     private const int MAX_FONT_REFRESHES = 2;
 
     private int m_textRefreshes = 0;
 
     public int minFontSize { get; set; }
     public int maxFontSize { get; set; }
 
     // Call this if the font size does not update by just setting the text
     // Should probably wait till the end of frame to get the real font size, instead of using this method
     public void SetText(string text)
     {
         this.text = text;
         UpdateFontSize();
     }
 
     private void OnGeometryChanged(GeometryChangedEvent evt)
     {
         UpdateFontSize();
     }
 
     private void UpdateFontSize()
     {
         if (m_textRefreshes < MAX_FONT_REFRESHES)
         {
             Vector2 textSize = MeasureTextSize(text, float.MaxValue, MeasureMode.AtMost, float.MaxValue, MeasureMode.AtMost);
             float fontSize = Mathf.Max(style.fontSize.value.value, 1); // Unity can return a font size of 0 which would break the auto fit // Should probably wait till the end of frame to get the real font size
             float heightDictatedFontSize = Mathf.Abs(contentRect.height);
             float widthDictatedFontSize = Mathf.Abs(contentRect.width / textSize.x) * fontSize;
             float newFontSize = Mathf.FloorToInt(Mathf.Min(heightDictatedFontSize, widthDictatedFontSize));
             newFontSize = Mathf.Clamp(newFontSize, minFontSize, maxFontSize);
             if (Mathf.Abs(newFontSize - fontSize) > 1)
             {
                 m_textRefreshes++;
                 style.fontSize = new StyleLength(new Length(newFontSize));
             }
         }
         else
         {
             m_textRefreshes = 0;
         }
     }
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by andrew-lukasik · Oct 16, 2021 at 07:33 PM


Here is my half-working prototype for a custom Label element that attempts to solve exactly that.


alt text


It's incomplete and with potential bugs (just a prototype), also with a requirement that you do not use flex grow (it produces undefined behaviour (recursion)) and use Size/Width [%] or Height [%] instead.

alt text

 // src* = https://gist.github.com/andrew-raphael-lukasik/8f65a4d7055e29f80376bcb4f9b500af
 using UnityEngine;
 using UnityEngine.UIElements;
 
 // IMPORTANT NOTE:
 // This elemeent doesn't work with flexGrow as it leads to undefined behaviour (recursion).
 // Use Size/Width[%] and Size/Height attributes</b> instead
 
 [UnityEngine.Scripting.Preserve]
 public class LabelAutoFit : UnityEngine.UIElements.Label
 {
 
     public Axis axis { get; set; }
     public float ratio { get; set; }
 
     [UnityEngine.Scripting.Preserve]
     public new class UxmlFactory : UxmlFactory<LabelAutoFit,UxmlTraits> {}
     
     [UnityEngine.Scripting.Preserve]
     public new class UxmlTraits : Label.UxmlTraits// VisualElement.UxmlTraits
     {
         UxmlFloatAttributeDescription _ratio = new UxmlFloatAttributeDescription{
             name = "ratio" ,
             defaultValue = 0.1f ,
             restriction = new UxmlValueBounds{ min="0.0" , max="0.9" , excludeMin=false , excludeMax=true }
         };
         UxmlEnumAttributeDescription<Axis> _axis = new UxmlEnumAttributeDescription<Axis>{
             name = "ratio-axis" ,
             defaultValue = Axis.Horizontal
         };
         public override void Init ( VisualElement ve , IUxmlAttributes bag , CreationContext cc )
         {
             base.Init( ve , bag , cc );
 
             LabelAutoFit instance = ve as LabelAutoFit;
             instance.RegisterCallback<GeometryChangedEvent>( instance.OnGeometryChanged );
 
             instance.ratio = _ratio.GetValueFromBag( bag , cc );
             instance.axis = _axis.GetValueFromBag( bag , cc );
             instance.style.fontSize = 1;// triggers GeometryChangedEvent
         }
     }
 
     void OnGeometryChanged ( GeometryChangedEvent evt )
     {
         float oldRectSize = this.axis==Axis.Vertical ? evt.oldRect.height : evt.oldRect.width;
         float newRectLenght = this.axis==Axis.Vertical ? evt.newRect.height : evt.newRect.width;
         
         float oldFontSize = this.style.fontSize.value.value;
         float newFontSize = newRectLenght * this.ratio;
         
         float fontSizeDelta = Mathf.Abs( oldFontSize - newFontSize );
         float fontSizeDeltaNormalized = fontSizeDelta / Mathf.Max(oldFontSize,1);
 
         if( fontSizeDeltaNormalized>0.01f )
             this.style.fontSize = newFontSize;
     }
 
     public enum Axis { Horizontal , Vertical }
 
 }

If sb knows how to improve on that, please do share your code too.


screenshot-2021-10-16-233942.jpg (57.2 kB)
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

133 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How do you scale text based on the number of characters? 1 Answer

Text "Best Fit" is not working for Bitmap fonts? 1 Answer

Make UI always center the panel 1 Answer

How do I calculate a text size with the Best Fit option using a TextGenerator 2 Answers

Adjusting size of the text to fit panel 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges