简体   繁体   English

Unity:找不到 UI 布局元素最大尺寸

[英]Unity: Can't find UI Layout Element Max Size

In Unity UI, LayoutElement has a min, prefered and flxible size, but it do not have a max size property.在 Unity UI 中,LayoutElement 具有最小、首选和可变大小,但没有最大大小属性。

For example if I have a text1 and例如,如果我有一个text1

layoutElement.flxibleWith = 1
layoutElement.minHeight  = 19

text1 with one line txt: text1一行 txt:

text1 一行 txt

But when I load text in text1 it continues spreading it height with no limits:但是当我在text1加载文本时,它会继续无限制地传播它的高度:

在此处输入图片说明

I have made a script:我做了一个脚本:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

[ExecuteInEditMode]
[RequireComponent(typeof(LayoutElement))]

public class LayoutElementMaxSize : MonoBehaviour
{

private LayoutElement layoutElement;
private ContentSizeFitter contentSizeFitter;
private RectTransform rectransform;

public bool controllWidth;
public bool controllHeight;

public float maxHight;
public float maxWidth;

void Start()
{
    layoutElement = GetComponent<LayoutElement>();
    rectransform = GetComponent<RectTransform>();
}

public void Update()
{
    if(rectransform.hasChanged)
     {
        rectransform.hasChanged = false;

        if (controllHeight)
        {
            layoutElement.preferredHeight = -1;

            layoutElement.CalculateLayoutInputHorizontal();
            layoutElement.CalculateLayoutInputVertical();

            if (rectransform.rect.height >= maxHight)
            {
                layoutElement.preferredHeight = maxHight;
            }
        }

        if (controllWidth)
        {
            if (rectransform.rect.height >= maxWidth)
            {
                layoutElement.preferredWidth = maxWidth;
            }
            else
            {
                layoutElement.preferredWidth = -1;
            }
        }
    }
}}

but it is not full filing my requirement plz take a look on it ..但它还没有完全满足我的要求,请看一看..

I know this is an old question, but I was looking for something like this and I end up rewriting your class and it now works fine for me.我知道这是一个老问题,但我一直在寻找类似的东西,最终我重写了你的课程,现在它对我来说很好用。 Instead of just making another MonoBehaviour I override the LayoutElement, I also added an custom inspector to make it easy to edit it.我没有再创建另一个 MonoBehaviour,而是覆盖了 LayoutElement,我还添加了一个自定义检查器,以便于对其进行编辑。 Hope my solution could help you or anyone else that would like something like this.希望我的解决方案可以帮助您或其他任何想要这样的人。

using UnityEngine;
using UnityEngine.UI;

#if UNITY_EDITOR
using UnityEditor;
#endif

[RequireComponent(typeof(RectTransform))]
[System.Serializable]
public class LayoutMaxSize : LayoutElement
{
    public float maxHeight = -1;
    public float maxWidth = -1;

    public override void CalculateLayoutInputHorizontal()
    {
        base.CalculateLayoutInputHorizontal();
        UpdateMaxSizes();
    }

    public override void CalculateLayoutInputVertical()
    {
        base.CalculateLayoutInputVertical();
        UpdateMaxSizes();
    }

    protected override void OnRectTransformDimensionsChange()
    {
        base.OnRectTransformDimensionsChange();
        UpdateMaxSizes();
    }

    protected override void OnValidate()
    {
        base.OnValidate();
        UpdateMaxSizes();
    }

    private void UpdateMaxSizes()
    {
        if (maxHeight != -1)
        {
            if (preferredHeight == -1 && maxHeight < GetComponent<RectTransform>().sizeDelta.y)
            {
                preferredHeight = maxHeight;
            }
            else if (preferredHeight != -1 && transform.childCount > 0)
            {
                bool first = true;
                float biggestY = 0;
                float lowestY = 0;
                for (int i = 0; i < transform.childCount; i++)
                {
                    var childrenTransform = transform.GetChild(i).GetComponent<RectTransform>();
                    if (childrenTransform == null) continue;
                    var childPos = childrenTransform.localPosition;
                    var childSize = childrenTransform.sizeDelta;
                    var childPivot = childrenTransform.pivot;
                    if(first)
                    {
                        biggestY = childPos.y + (childSize.y * (1f - childPivot.y));
                        lowestY = childPos.y - (childSize.y * childPivot.y);
                    }
                    else
                    {
                        biggestY = Mathf.Max(biggestY, childPos.y + (childSize.y * (1f - childPivot.y)));
                        lowestY = Mathf.Min(lowestY, childPos.y - (childSize.y * childPivot.y));
                    }
                    first = false;
                }
                if (first) return;
                var childrenYSize = Mathf.Abs(biggestY - lowestY);
                if(preferredHeight > childrenYSize)
                {
                    preferredHeight = -1;
                }
            }
        }
        if (maxWidth != -1)
        {
            if (preferredWidth == -1 && maxWidth < GetComponent<RectTransform>().sizeDelta.x)
            {
                preferredWidth = maxWidth;
            }
            else if (preferredWidth != -1 && transform.childCount > 0)
            {
                bool first = true;
                float biggestX = 0;
                float lowestX = 0;
                for (int i = 0; i < transform.childCount; i++)
                {
                    var childrenTransform = transform.GetChild(i).GetComponent<RectTransform>();
                    if (childrenTransform == null) continue;
                    var childPos = childrenTransform.localPosition;
                    var childSize = childrenTransform.sizeDelta;
                    var childPivot = childrenTransform.pivot;
                    if (first)
                    {
                        biggestX = childPos.x + (childSize.x * (1f - childPivot.x));
                        lowestX = childPos.x - (childSize.x * childPivot.x);
                    }
                    else
                    {
                        biggestX = Mathf.Max(biggestX, childPos.x + (childSize.x * (1f - childPivot.x)));
                        lowestX = Mathf.Min(lowestX, childPos.x - (childSize.x * childPivot.x));
                    }
                    first = false;
                }
                if (first) return;
                var childrenXSize = Mathf.Abs(biggestX - lowestX);
                if (preferredWidth > childrenXSize)
                {
                    preferredWidth = -1;
                }
            }
        }
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(LayoutMaxSize))]
public class LayoutMaxSizeEditor : Editor
{
    public override void OnInspectorGUI()
    {
        LayoutMaxSize layoutMax = target as LayoutMaxSize;
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel("Ignore Layout");
        layoutMax.ignoreLayout = EditorGUILayout.Toggle(layoutMax.ignoreLayout);
        EditorGUILayout.EndHorizontal();
        if (!layoutMax.ignoreLayout)
        {
            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Min Width");
            var allowMinWidth = EditorGUILayout.Toggle(layoutMax.minWidth != -1);
            if (allowMinWidth)
            {
                if (layoutMax.minWidth == -1) layoutMax.minWidth = 0;
                layoutMax.minWidth = EditorGUILayout.FloatField(layoutMax.minWidth);
            }
            else if (layoutMax.minWidth != -1)
            {
                layoutMax.minWidth = -1;
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Min Height");
            var allowMinHeight = EditorGUILayout.Toggle(layoutMax.minHeight != -1);
            if (allowMinHeight)
            {
                if (layoutMax.minHeight == -1) layoutMax.minHeight = 0;
                layoutMax.minHeight = EditorGUILayout.FloatField(layoutMax.minHeight);
            }
            else if (layoutMax.minHeight != -1)
            {
                layoutMax.minHeight = -1;
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Max Width");
            var allowMaxWidth = EditorGUILayout.Toggle(layoutMax.maxWidth != -1);
            if (allowMaxWidth)
            {
                if (layoutMax.maxWidth == -1) layoutMax.maxWidth = Mathf.Max(0, layoutMax.minWidth);
                layoutMax.maxWidth = Mathf.Max(EditorGUILayout.FloatField(layoutMax.maxWidth), layoutMax.minWidth);
            }
            else if(layoutMax.maxWidth != -1)
            {
                layoutMax.maxWidth = -1;
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Max Height");
            var allowMaxHeight = EditorGUILayout.Toggle(layoutMax.maxHeight != -1);
            if (allowMaxHeight)
            {
                if (layoutMax.maxHeight == -1) layoutMax.maxHeight = Mathf.Max(0, layoutMax.minHeight);
                layoutMax.maxHeight = Mathf.Max(EditorGUILayout.FloatField(layoutMax.maxHeight), layoutMax.minHeight);
            }
            else if (layoutMax.maxHeight != -1)
            {
                layoutMax.maxHeight = -1;
            }
            EditorGUILayout.EndHorizontal();
        }
    }
}
#endif

I wrote a new script which includes maxheight and maxwidth field for layout element it is not fuly tested but if you want you can use it.我写了一个新脚本,其中包括布局元素的 maxheight 和 maxwidth 字段,它没有经过全面测试,但如果您愿意,可以使用它。

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UI;
#endif

[RequireComponent(typeof(RectTransform))]
[System.Serializable]
public class LayoutElementWithMaxValues : LayoutElement {

    public float maxHeight;
    public float maxWidth;

    public bool useMaxWidth;
    public bool useMaxHeight;

    bool ignoreOnGettingPreferedSize;

    public override int layoutPriority { 
        get => ignoreOnGettingPreferedSize ? -1 : base.layoutPriority; 
        set => base.layoutPriority = value; }

    public override float preferredHeight {
        get {
            if (useMaxHeight) {
                var defaultIgnoreValue = ignoreOnGettingPreferedSize;
                ignoreOnGettingPreferedSize = true;

                var baseValue = LayoutUtility.GetPreferredHeight(transform as RectTransform);

                ignoreOnGettingPreferedSize = defaultIgnoreValue;

                return baseValue > maxHeight ? maxHeight : baseValue;
            }
            else
                return base.preferredHeight;
        }
        set => base.preferredHeight = value;
    }

    public override float preferredWidth { 
        get {
            if (useMaxWidth) {
                var defaultIgnoreValue = ignoreOnGettingPreferedSize;
                ignoreOnGettingPreferedSize = true;

                var baseValue = LayoutUtility.GetPreferredWidth(transform as RectTransform);

                ignoreOnGettingPreferedSize = defaultIgnoreValue;

                return baseValue > maxWidth ? maxWidth : baseValue;
            }
            else
                return base.preferredWidth;
        } 
        set => base.preferredWidth = value; 
    }

}

#if UNITY_EDITOR
[CustomEditor(typeof(LayoutElementWithMaxValues), true)]
[CanEditMultipleObjects]
public class LayoutMaxSizeEditor : LayoutElementEditor {
    LayoutElementWithMaxValues layoutMax;

    SerializedProperty maxHeightProperty;
    SerializedProperty maxWidthProperty;

    SerializedProperty useMaxHeightProperty;
    SerializedProperty useMaxWidthProperty;

    RectTransform myRectTransform;

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

        layoutMax = target as LayoutElementWithMaxValues;
        myRectTransform = layoutMax.transform as RectTransform;

        maxHeightProperty = serializedObject.FindProperty(nameof(layoutMax.maxHeight));
        maxWidthProperty = serializedObject.FindProperty(nameof(layoutMax.maxWidth));

        useMaxHeightProperty = serializedObject.FindProperty(nameof(layoutMax.useMaxHeight));
        useMaxWidthProperty = serializedObject.FindProperty(nameof(layoutMax.useMaxWidth));
    }

    public override void OnInspectorGUI() {

        Draw(maxWidthProperty, useMaxWidthProperty);
        Draw(maxHeightProperty, useMaxHeightProperty);

        serializedObject.ApplyModifiedProperties();

        EditorGUILayout.Space();

        base.OnInspectorGUI();
    }

    void Draw(SerializedProperty property, SerializedProperty useProperty) {
        Rect position = EditorGUILayout.GetControlRect();

        GUIContent label = EditorGUI.BeginProperty(position, null, property);

        Rect fieldPosition = EditorGUI.PrefixLabel(position, label);

        Rect toggleRect = fieldPosition;
        toggleRect.width = 16;

        Rect floatFieldRect = fieldPosition;
        floatFieldRect.xMin += 16;


        var use = EditorGUI.Toggle(toggleRect, useProperty.boolValue);
        useProperty.boolValue = use;

        if (use) {
            EditorGUIUtility.labelWidth = 4;
            property.floatValue = EditorGUI.FloatField(floatFieldRect, new GUIContent(" "), property.floatValue);
            EditorGUIUtility.labelWidth = 0;
        }


        EditorGUI.EndProperty();
    }

}

#endif

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM