sisi mendel
sisi mendel

Reputation: 799

Unity3D - "Parent has a type of layout group" error

I have this simple structure inside a Canvas:

Now, it works pretty well, when the text gets out of boundaries, the UI-Image expands. But since I have a Layout Group as a parent to my TMP Text, I get an error inside the Text, in the Content Size Fitter, saying that 'The parent has a a type of layout group component...'. And as a result, the image height sometimes doesn't update when I the text changes (doesn't grow or shrink, only after I refresh or save the project).

enter image description here enter image description here

Am I doing something wrong here?

Upvotes: 14

Views: 24270

Answers (5)

Ritesh Khokhani
Ritesh Khokhani

Reputation: 59

Follow the steps below to achieve your UI design goal..

  1. Add Horizontal Layout Group to your container image component and enable Width of Control Child Size
  2. Add Content Size Fitter to your container image component and set Horizontal Fit to Preferred Size

You don't need to add any component to your text component. You can also add currency icon as show below.

enter image description hereenter image description here

enter image description here

Upvotes: 1

Andrew B
Andrew B

Reputation: 3

The simplest solution, if suddenly someone else is relevant.

Create a standard ScrollView, remove "Content" from it and add text instead of content (do not forget to add your text to the Content field in ScrollRect). Next, add ContentSizeFittier to the text.enter image description here

Upvotes: 0

Adem Rodriguez
Adem Rodriguez

Reputation: 21

made a custom script duplicated from the original contentSizeFitter component in which i added a bool called applyToParent , if "true" & the parent has a rectTransform component , the parent will scale along the current object. you can even add a list of recttransforms variable which you can make them follow the same size as well! screenshot

using UnityEngine;
using UnityEngine.EventSystems;

namespace UnityEngine.UI
{
    [AddComponentMenu("Layout/Custom Content Size Fitter", 888)]
    [ExecuteAlways]
    [RequireComponent(typeof(RectTransform))]
    /// <summary>
    /// Resizes a RectTransform to fit the size of its content & the ability to modify the size of the parent as well
    /// </summary>
    /// <remarks>
    /// The ContentSizeFitter can be used on GameObjects that have one or more ILayoutElement components, such as Text, Image, HorizontalLayoutGroup, VerticalLayoutGroup, and GridLayoutGroup.
    /// </remarks>
    public class CustomContentSizeFitter :  UIBehaviour, ILayoutSelfController
    {
        /// <summary>
        /// The size fit modes avaliable to use.
        /// </summary>
        public enum FitMode
        {
            /// <summary>
            /// Don't perform any resizing.
            /// </summary>
            Unconstrained,
            /// <summary>
            /// Resize to the minimum size of the content.
            /// </summary>
            MinSize,
            /// <summary>
            /// Resize to the preferred size of the content.
            /// </summary>
            PreferredSize
        }
        [SerializeField] protected FitMode m_HorizontalFit = FitMode.Unconstrained;
       
       
        /// <summary>
        /// The fit mode to use to determine the width.
        /// </summary>
        public FitMode horizontalFit { get { return m_HorizontalFit; } set { if (SetPropertyUtility2.SetStruct(ref m_HorizontalFit, value)) SetDirty(); } }

        [SerializeField] protected FitMode m_VerticalFit = FitMode.Unconstrained;

        /// <summary>
        /// The fit mode to use to determine the height.
        /// </summary>
        public FitMode verticalFit { get { return m_VerticalFit; } set { if (SetPropertyUtility2.SetStruct(ref m_VerticalFit, value)) SetDirty(); } }


        private DrivenRectTransformTracker m_Tracker;

        protected CustomContentSizeFitter()
        {}

        protected override void OnEnable()
        {
            base.OnEnable();
            SetDirty();
        }

        protected override void OnDisable()
        {
            m_Tracker.Clear();
            LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
            base.OnDisable();
        }

        protected override void OnRectTransformDimensionsChange()
        {
            SetDirty();
        }

        public virtual void SetLayoutHorizontal()
        {
            m_Tracker.Clear();
            HandleSelfFittingAlongAxis(0);
        }

        /// <summary>
        /// Calculate and apply the vertical component of the size to the RectTransform
        /// </summary>
        public virtual void SetLayoutVertical()
        {
            HandleSelfFittingAlongAxis(1);
        }
        [System.NonSerialized] private RectTransform m_Rect;
        [System.NonSerialized] private RectTransform m_parentRect;
        private RectTransform rectTransform
        {
            get
            {
                if (m_Rect == null)
                    m_Rect = GetComponent<RectTransform>();
                return m_Rect;
            }
        }
        private RectTransform parentRectTransform
        {
            get
            {
                if (m_parentRect == null)
                    m_parentRect = rectTransform.parent.GetComponent<RectTransform>();
                return m_parentRect;
            }
        }
        private void HandleSelfFittingAlongAxis(int axis)
        {
            FitMode fitting = (axis == 0 ? horizontalFit : verticalFit);
            if (fitting == FitMode.Unconstrained)
            {
                // Keep a reference to the tracked transform, but don't control its properties:
                m_Tracker.Add(this, rectTransform, DrivenTransformProperties.None);
                return;
            }

            m_Tracker.Add(this, rectTransform, (axis == 0 ? DrivenTransformProperties.SizeDeltaX : DrivenTransformProperties.SizeDeltaY));

            // Set size to min or preferred size
            if (fitting == FitMode.MinSize)
                rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetMinSize(m_Rect, axis));
            else
                rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetPreferredSize(m_Rect, axis));
            
            if(applyToParent && parentRectTransform != null )
            {
                if(fitting == FitMode.MinSize )
                    parentRectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetMinSize(m_Rect, axis));
                else
                    parentRectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetPreferredSize(m_Rect, axis));
            }
        }
        public bool applyToParent = true;

        protected void SetDirty()
        {
            if (!IsActive())
                return;

            LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
        }

        #if UNITY_EDITOR
        protected override void OnValidate()
        {
            SetDirty();
        }
        #endif

    }

    public static class SetPropertyUtility2
    {
        public static bool SetColor(ref Color currentValue, Color newValue)
        {
            if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b && currentValue.a == newValue.a)
                return false;

            currentValue = newValue;
            return true;
        }

        public static bool SetStruct<T>(ref T currentValue, T newValue) where T: struct
        {
            if (currentValue.Equals(newValue))
                return false;

            currentValue = newValue;
            return true;
        }

        public static bool SetClass<T>(ref T currentValue, T newValue) where T: class
        {
            if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
                return false;

            currentValue = newValue;
            return true;
        }

    }
    
    
}

Upvotes: 1

ArtS
ArtS

Reputation: 2012

I've been haunted by this problems for over 1 year, finally got it done in a proper way.

The solution is very simple:

  1. check "Control child size width/height" on the layout group component of the parent object.
  2. delete content size fitter of any child object.

Upvotes: 11

Tricko
Tricko

Reputation: 551

I will convert this to answer since I'm going to attach images. I did something similar to this for a chat feature.

  1. Make the parent have the content size fitter and set either the horizontal or vertical fit to preferred size. ContentSizeFitter in Parent

  2. Let its immediate child be the background, and add a layout element to it to control its minimum size. Also add a layout group to it to control the text that you will put as a child to it. BackgroundMinSize

  3. Add the text as a child of background CurrentText

  4. Change the text to check the background. ExpandedChild

[EDIT] 1. I changed the Parent's layout group to VerticalLayoutGroup. 2. I made a duplicate of the game object "Background" but with different texts to that you can see how the ContentSizeFitter and VerticalLayoutGroup controls the size of the children. DuplicateGameObjects Result

In the screenshots above, I never adjusted anything on the rect transform. I just changed the text, and as you can see, the background of each text/dialog/message also adjusted.

Upvotes: 24

Related Questions