Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

Multiline TMP_InputField, auto-resize height while editing.

Discussion in 'UGUI & TextMesh Pro' started by Peeling, Mar 8, 2019.

  1. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    I have been trying to get this to work all day with no success. I have searched for answers, found many, tried them all, had no success. I have tried every combination of layout elements, vertical layouts, content size fitters on every combination of the various elements to no avail.

    I tried hooking into value-changed and manually asking the text component for its preferred size. This did not work because the text component's preferred size ignores its wrapping setting (so hitting return makes the box taller, but wrapping lines does not).

    If I disable the Rect Mask I can see the text overflowing the input field area, but there seems to be no way at all to get 'how big it is' and position the input field around it.

    This seems like such a basic, simple, fundamental thing to want to do; I don't understand why it's... impossible.
     
  2. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    So, forty more minutes of plugging away and a variant on one of the suggested solutions seems to be working - though it's very ugly:

    1. Make the input field object a child of a TMP_Text object. Make sure the parent text object has the same settings as the input field's text object. NOTE: Be sure to open up and set the 'extra settings' margins to match the InputField's TextArea child's left/top/right/bottom values.

    2. Add a Context Size Fitter to the parent Text object, and a Layout Element with an appropriate minimum height (otherwise it'll shrink to nothing). Set the Context Size Fitter's vertical fit to 'Preferred Size'.

    3. Make sure the InputField's rect transform is set to 'stretch', with zero L/T/R/B.

    4. Now write a script that copies the InputField's text to the parent Text, and make sure that gets called On Value Changed.

    Here's the trick that made it work for me: When copying up the text, check to see if the last character is a carriage return ("\n"). If it is, stick another character on the end. This is because the parent text object will silently ignore empty lines at the bottom, but the input field WON'T, which means the two get out of sync and you get text wandering off the top of the field area.

    If you've done everything right (DON'T forget the extra settings margins, otherwise the two text areas will be different sizes and get out of sync), this seems to be a fairly robust (if bloody ugly and inefficient) way of getting an auto-resizing multi-line text input field.

    It even worked when I manually resized the width of the parent text box when it was full of text at runtime, so for now at least I can make some progress.
     
    Flavelius likes this.
  3. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    The TMP Input Field does not currently implement the ILayoutElement interface which is why Layout Components are not working with it.

    I am currently looking into this. I'll reply to this post as soon as I have more information to share.

    P.S. Support for Layout Components should have been added a while back which is why I am looking into this as we speak.
     
  4. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    That's great, thank you!
     
  5. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    Here are the changes to the TMP_InputField.cs file required to add support for Layout Components.

    upload_2019-3-9_16-42-4.png

    In order for the Input Field to behave correctly (as far as I can tell based on my limited testing) the following changes to the structure of the parent and child objects is required.



    Give this a try and let me know if it behaves as expected.
     
  6. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    Sorry, I'm only just getting back to this now - trying it ASAP. Thanks!
     
  7. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    My TMP_Inputfield.cs file is MUCH shorter than yours! Am I out of date?
     
  8. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    I made all those changes, and I get this error while typing into the box:

    Trying to add TextMeshPro - InputField Input Caret (TMPro.TMP_SelectionCaret) for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.
    UnityEngine.RectTransform:set_anchorMin(Vector2)
    TMPro.TMP_InputField:AssignPositioningIfNeeded() (at Library/PackageCache/com.unity.textmeshpro@1.3.0/Scripts/Runtime/TMP_InputField.cs:2743)
    TMPro.TMP_InputField:AdjustRectTransformRelativeToViewport(Vector2, Single, Boolean) (at Library/PackageCache/com.unity.textmeshpro@1.3.0/Scripts/Runtime/TMP_InputField.cs:2999)
    TMPro.TMP_InputField:GenerateCaret(VertexHelper, Vector2) (at Library/PackageCache/com.unity.textmeshpro@1.3.0/Scripts/Runtime/TMP_InputField.cs:2835)
    TMPro.TMP_InputField:OnFillVBO(Mesh) (at Library/PackageCache/com.unity.textmeshpro@1.3.0/Scripts/Runtime/TMP_InputField.cs:2774)
    TMPro.TMP_InputField:UpdateGeometry() (at Library/PackageCache/com.unity.textmeshpro@1.3.0/Scripts/Runtime/TMP_InputField.cs:2719)
    TMPro.TMP_InputField:Rebuild(CanvasUpdate) (at Library/PackageCache/com.unity.textmeshpro@1.3.0/Scripts/Runtime/TMP_InputField.cs:2673)
    UnityEngine.Canvas:SendWillRenderCanvases()
     
  9. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    Most likely you forgot to add the Layout Element to the Placeholder and set it to ignore.

    Also these changes most likely will require you use version 1.4.0-preview.3a.
     
  10. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    Thanks :) I'll return to this when I've updated.
     
  11. Peeling

    Peeling

    Joined:
    Nov 10, 2013
    Posts:
    443
    Okay, I've tried with the settings you suggested and the 1.4.0 release. I definitely have all the right components and settings, but as soon as what I'm typing into the box reaches the right hand side I start getting error spam about trying to add the caret for a graphic rebuild while in a rebuild loop.

    Apart from that it almost works - but there's a problem. I want the box to auto-expand horizontally too, but setting the content size fitter to 'preferred' horizontally makes the box zero width and impossible to click on when empty. If I add a layout element to the text to force a minimum width, it seems to interact badly; the text and caret jump around all over the place while I'm typing.
     
  12. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    Can you export / provide me a Repro project / scene to take a look at?
     
  13. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    The following additional changes should get you the functionality you seek,

    upload_2019-4-2_15-41-26.png

    In terms of the zero width, add a Layout Element to the Input Field parent as seen below. This will enable you to set a minimum size for it.

    upload_2019-4-2_15-42-55.png

     
    Last edited: Apr 2, 2019
  14. ConorArup

    ConorArup

    Joined:
    Feb 15, 2018
    Posts:
    17
    Hi Stephan,

    I've updated to both 1.40 preview 3a and 1.40 and I don't seem any of the code that is shown in the last addition screenshot (lines 4041).

    I also seem to be experiencing a separate issue. I'm trying to contain mine within a ScrollView. I've got it working with the various setups suggested above, however, I have two issues:
    • Firstly, when the input reaches the end of the content area and thus increments past the mask, the scrollbar doesn't update which means you have to keep dragging the scrollbar down to view the latest text. This could be solved by setting the scrollbar value to 0 or 1 onValueChanged but then if you start editing the text in the middle of the content area it would just snap it back down. Do you have any suggestions for fixing this?
      • I'm aware the TextMeshPro InputField has a scrollbar property but I can't seem to get this to work at all? If I put the InputField outside of the ScrollView then there is no mask? I think I'm missing something pretty obvious.
    • Secondly, if I use the mouse scroll wheel while hovering over the input field the content just disappears until I start typing again. Any idea?
     
    Last edited: Apr 18, 2019
  15. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,596
    These changes haven't been released yet. They will be included in version 1.4.2 for Unity 2018.3 and 2.0.2 for Unity 2019.2.

    Until the required changes, the input field will be misbehaving with layout components.
     
  16. nikix22

    nikix22

    Joined:
    Jan 16, 2015
    Posts:
    25
    Hi :) I was getting the same error like you described, and I FIXED IT! :)
    My InputField was inside Canvas which had PixelPerfect option checked on.
    When I unchecked PixelPerfect, error disapeared :)
    Greets!
     
  17. dark_ahimas

    dark_ahimas

    Joined:
    Dec 24, 2020
    Posts:
    1
    Dear Stephan_B,
    Could you, please, update if that situation with below porblem is solved somehow?
    I've added and set all layout elements as you described, but TMP_InputField is still doesn't have auto-resize height while editing.

    Thank you for your reply.

    Quote of error:
    Trying to add Caret (TMPro.TMP_SelectionCaret) for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.
    UnityEngine.RectTransform:set_sizeDelta (UnityEngine.Vector2)
    TMPro.TMP_InputField:AssignPositioningIfNeeded () (at Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_InputField.cs:3531)
    TMPro.TMP_InputField:AdjustRectTransformRelativeToViewport (UnityEngine.Vector2,single,bool) (at Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_InputField.cs:3876)
    TMPro.TMP_InputField:GenerateCaret (UnityEngine.UI.VertexHelper,UnityEngine.Vector2) (at Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_InputField.cs:3640)
    TMPro.TMP_InputField:OnFillVBO (UnityEngine.Mesh) (at Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_InputField.cs:3563)
    TMPro.TMP_InputField:UpdateGeometry () (at Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_InputField.cs:3504)
    TMPro.TMP_InputField:Rebuild (UnityEngine.UI.CanvasUpdate) (at Library/PackageCache/com.unity.textmeshpro@3.0.6/Scripts/Runtime/TMP_InputField.cs:3479)
    UnityEngine.Canvas:SendWillRenderCanvases ()
     
  18. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    547
    Is this still up to date?
    Do we have to modify the source file or is this included now with the newer version?

    I try to make a multiline TMP Input with auto size (height) but no matter what I try, it doesn't seem to work.

    I tried every google solution with vertical layout groups, content size fitter etc
    I tried your solution but the text just starts to flicker like crazy and sometimes even throws exceptions (similar to the one posted above)

    Im really confused why it is so hard to achieve dynamic / auto text height with TMP input,
    dynamic text height for a normal text mesh was very easy, but this input field is driving me crazy


    Update:
    To add more details, I have a ScrollView with a Content object which already has a Vertical Layout Group and a ContentSizeFitter to match the height of the child elements, so the scroll viewer works properly, the TMP input is one child element and I simply wanted to show all (multiline) text of the TMP input which a nested scrollbar.

    I found a working "solution" by adding the TMP input directly to the Content object and adding an additional ContentSizeFitter to the input GO, without any additional Layout Groups on the Input or TextArea object.

    This is the only working solution so far, which is kinda funny, because it gives me a warning on the input ContentSizeFitter, because the parent object already has a LayoutGroup and ContentSizeFitter.

    So can I just ignore this warning or is there any better / "official" solution for this case?

    I think the TMP input should adjust the size without the additional ContentSizeFitter, if the parent already has a ContentSizeFitter and LayoutGroup, is this a bug or why is the additional, nested ContentSizeFitter required?
     
    Last edited: Jul 11, 2022
  19. ThePilgrim

    ThePilgrim

    Joined:
    Apr 25, 2013
    Posts:
    17