繁体   English   中英

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

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

在 Unity UI 中,LayoutElement 具有最小、首选和可变大小,但没有最大大小属性。

例如,如果我有一个text1

layoutElement.flxibleWith = 1
layoutElement.minHeight  = 19

text1一行 txt:

text1 一行 txt

但是当我在text1加载文本时,它会继续无限制地传播它的高度:

在此处输入图片说明

我做了一个脚本:

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;
            }
        }
    }
}}

但它还没有完全满足我的要求,请看一看..

我知道这是一个老问题,但我一直在寻找类似的东西,最终我重写了你的课程,现在它对我来说很好用。 我没有再创建另一个 MonoBehaviour,而是覆盖了 LayoutElement,我还添加了一个自定义检查器,以便于对其进行编辑。 希望我的解决方案可以帮助您或其他任何想要这样的人。

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

我写了一个新脚本,其中包括布局元素的 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