获取UI文本元素高度不正确的Unity

时间:2018-09-05 14:43:26

标签: c# user-interface unity3d text

我有一些代码可以为文本元素设置自定义,然后像这样自动调整高度:

Title.SetTextContainerSize("autoH", 330);

public void SetTextContainerSize(string fit, float dimension = 0)
    {
        if (UIElement.GetComponent<ContentSizeFitter>() == null)
            UISizeFitterComponent = UIElement.AddComponent(typeof(ContentSizeFitter)) as ContentSizeFitter;

        if (fit == "autoWH")
        {
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
            base.SetDimensions( RectOptions.sizeDelta);
        }
        else if (fit == "autoW")
        {
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
            base.SetDimensions( new Vector2(RectOptions.rect.width, dimension));
        }
        else if (fit == "autoH")
        { //here is a problem.. 
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
            Canvas.ForceUpdateCanvases();
            Debug.Log(new Vector2(dimension, RectOptions.rect.height));
            base.SetDimensions( new Vector2(dimension, RectOptions.rect.height));
        }
    }

编辑:添加了设置尺寸功能

public void SetDimensions(Vector2 dimensions)
    {
        RectOptions.sizeDelta = dimensions;
        Dimensions = dimensions; //this just sets the value of a property. 
    }

但是当我调用函数更新文本时,我从Debug.Log()得到以下结果,它说宽度= 330,高度为2077。在这种情况下,宽度是正确的,但高度甚至不是关。

在此处查看实际元素及其正确高度的屏幕截图。 enter image description here

编辑2 我的统一版本是2018.1.3f1

更新元素的实际高度时我做错了什么?

如果有其他完全替代的方法,我也愿意在必要时完全重写当前函数:)

如果不清楚,请告诉我,以便我澄清!

编辑3 我决定添加使用该功能的类的完整代码以及调用相应函数的代码,也许是存在导致错误的问题:

这是调用普通功能的代码:

var Title = new EasyText(new Vector2(390, -20), Vector2.zero, Data.title, 30, _color: new Color(0,0,0,1));
Title.SetTextContainerSize("autoH", 330);
Main.MainCanvas.Add(Title);

var titleBottom = (Title.Dimensions.y);
Debug.Log(titleBottom);

这是上面的代码调用的类:

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

namespace Easy.UI
{

    public static class EasyUISettings
    {
        public struct AnchorPoints
        {
            public static readonly Vector2 TopLeft = new Vector2(0, 1);
            public static readonly Vector2 Center = new Vector2(0.5f, 0.5f);
            public static readonly Vector2 CenterLeft = new Vector2(0, 0.5f);
            public static readonly Vector2 CenterRight = new Vector2(1, 0.5f);
            public static readonly Vector2 TopCenter = new Vector2(0.5f, 1);
            public static readonly Vector2 BottomCenter = new Vector2(0.5f, 0);
        }

        public struct CoordinateReference
        {
            private CoordinateReference(int minX, int maxX, int minY, int maxY)
            {
                AnchorMin = new Vector2(minX, minY);
                AnchorMax = new Vector2(maxX, maxY);
            }

            public Vector2 AnchorMin { get; set; }
            public Vector2 AnchorMax { get; set; }

            public static readonly CoordinateReference TopLeft = new CoordinateReference(0, 0, 1, 1);
            public static readonly CoordinateReference TopRight = new CoordinateReference(1, 1, 1, 1);
            public static readonly CoordinateReference BottomLeft = new CoordinateReference(0, 0, 0, 0);
            public static readonly CoordinateReference BottomRight = new CoordinateReference(1, 1, 0, 0);

        }

        public struct TextAlignment
        {
            public static readonly TextAnchor TopLeft = TextAnchor.UpperLeft;
            public static readonly TextAnchor TopRight = TextAnchor.UpperRight;
            public static readonly TextAnchor TopCenter = TextAnchor.UpperCenter;
            public static readonly TextAnchor CenterLeft = TextAnchor.MiddleLeft;
            public static readonly TextAnchor CenterRight = TextAnchor.MiddleRight;
            public static readonly TextAnchor CenterCenter = TextAnchor.MiddleCenter;
            public static readonly TextAnchor BottomLeft = TextAnchor.LowerLeft;
            public static readonly TextAnchor BottomCenter = TextAnchor.LowerCenter;
            public static readonly TextAnchor BottomRight = TextAnchor.LowerRight;
        }
    }

    public static class EasyUIHelpers
    {
        public static void DestroyUIElement(EasyUIELementFoundation element)
        {
            element.DestroyUIElement();
            element = null;
        }
    }

    public class EasyCanvas
    {

        private GameObject CanvasObject, Events;
        private RectTransform Rect;
        private Canvas CanvasScript;
        private CanvasScaler Scaler;
        private GraphicRaycaster Raycaster;
        private StandaloneInputModule Inputs;
        private List<EasyUIELementFoundation> CanvasElements;

        public EasyCanvas()
        {
            CanvasElements = new List<EasyUIELementFoundation>();

            CanvasObject = new GameObject();
            CanvasObject.name = "EasyCanvas";
            Rect = CanvasObject.AddComponent(typeof(RectTransform)) as RectTransform;
            CanvasScript = CanvasObject.AddComponent(typeof(Canvas)) as Canvas;
            Scaler = CanvasObject.AddComponent(typeof(CanvasScaler)) as CanvasScaler;
            Raycaster = CanvasObject.AddComponent(typeof(GraphicRaycaster)) as GraphicRaycaster;

            CanvasScript.pixelPerfect = true;

            Events = new GameObject();
            Events.name = "EasyEventsHandler";
            Events.AddComponent(typeof(EventSystem));
            Inputs = Events.AddComponent(typeof(StandaloneInputModule)) as StandaloneInputModule;
        }

        public EasyCanvas(string _type, Camera c) : this()
        {
            CanvasScript.worldCamera = c;
            CanvasScript.planeDistance = 0.15f;

            if (_type.Equals("Camera"))
            {
                CanvasScript.renderMode = RenderMode.ScreenSpaceCamera;
                Scaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
                Scaler.referenceResolution = new Vector2(1920, 1080);
                Scaler.screenMatchMode = CanvasScaler.ScreenMatchMode.MatchWidthOrHeight;
            }
            else if(_type.Equals("World"))
                CanvasScript.renderMode = RenderMode.WorldSpace;
        }

        public void Add(EasyUIELementFoundation element)
        {
            element.AddToCanvas(CanvasScript);
            CanvasElements.Add(element);
        }

        public void EmptyCanvas()
        {
            for (int i = CanvasElements.Count - 1; i >= 0 ; i--)
            {
                CanvasElements[i].DestroyUIElement();
                CanvasElements[i] = null;
                CanvasElements.RemoveAt(i);
            }
        }

        public Vector2 GetCanvasDimensions()
        {
            return Rect.sizeDelta;
        }
    }

    public abstract class EasyUIELementFoundation
    {
        protected GameObject UIElement;
        protected RectTransform RectOptions;
        public Vector2 Position { get; private set; }
        public Vector2 Dimensions { get; private set; }
        public Vector2 PivotPoint { get; private set; }
        public EasyUISettings.CoordinateReference ReferenceCoordinates { get; private set; }

        protected EasyUIELementFoundation(Vector2 _position, Vector2 _dimensions)
        {
            UIElement = new GameObject();
            RectOptions = UIElement.AddComponent(typeof(RectTransform)) as RectTransform;
            SetPivotReference(EasyUISettings.AnchorPoints.TopLeft);
            SetCoordinateReference(EasyUISettings.CoordinateReference.TopLeft);
            SetPosition(_position);
            SetDimensions(_dimensions);
        }

        public void SetCoordinateReference(EasyUISettings.CoordinateReference reference)
        {
            RectOptions.anchorMin = reference.AnchorMin;
            RectOptions.anchorMax = reference.AnchorMax;
            ReferenceCoordinates = reference;
        }

        public void SetPivotReference(Vector2 reference)
        {
            RectOptions.pivot = reference;
            PivotPoint = reference;
        }

        public void SetPosition(Vector2 pos)
        {
            RectOptions.anchoredPosition = pos;
            Position = pos;
        }

        public void SetDimensions(Vector2 dimensions)
        {
            RectOptions.sizeDelta = dimensions;
            Dimensions = dimensions;
        }

        public void AddToCanvas(Canvas c)
        {
            UIElement.transform.SetParent(c.transform, false);
        }

        public void DestroyUIElement()
        {
            Object.Destroy(UIElement);
        }
    }

    public class EasyText : EasyUIELementFoundation
    {
        protected ContentSizeFitter UISizeFitterComponent;
        protected Text UITextComponent;
        public string Text { get; private set; }
        public Color TextColor { get; private set; }
        public Font TextFont { get; private set; }
        public int FontSize { get; private set; }
        public TextAnchor TextAlignment { get; private set; }

        public EasyText(Vector2 _position = default(Vector2), Vector2 _dimensions = default(Vector2), string _text = "Base Text", int _fontSize = 15, Font _font = null, Color _color = default(Color), TextAnchor _align = default(TextAnchor)) : base(_position, _dimensions)
        {
            UITextComponent = UIElement.AddComponent(typeof(Text)) as Text;
            SetText(_text);
            SetTextSize(_fontSize);
            SetFont(_font);
            SetTextColor(_color);
            SetTextAlignment(_align);
        }

        public void SetText(string text)
        {
            Text = text;
            UITextComponent.text = Text;
        }

        public void SetTextSize(int size)
        {
            FontSize = size;
            UITextComponent.fontSize = size;
        }

        public void SetFont(UnityEngine.Object font)
        {
            var ValidFont = (Font)font;
            if(ValidFont != null)
            {
                TextFont = ValidFont;
                UITextComponent.font = TextFont;
            }
            else
            {
                TextFont = Resources.GetBuiltinResource(typeof(Font), "Arial.ttf") as Font;
                UITextComponent.font = TextFont;
                Debug.LogWarning("No font was specified using default font");
            }
        }

        public void SetTextColor(Color color)
        {
            TextColor = color;
            UITextComponent.color = TextColor;
        }

        public void SetTextAlignment(TextAnchor alignment)
        {
            TextAlignment = alignment;
            UITextComponent.alignment = alignment;
        }

        public void SetTextContainerSize(string fit, float dimension = 0)
        {
            if (UIElement.GetComponent<ContentSizeFitter>() == null)
                UISizeFitterComponent = UIElement.AddComponent(typeof(ContentSizeFitter)) as ContentSizeFitter;

            if (fit == "autoWH")
            {
                UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
                UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
                base.SetDimensions( RectOptions.sizeDelta);
            }
            else if (fit == "autoW")
            {
                UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
                UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.Unconstrained;
                base.SetDimensions( new Vector2(RectOptions.rect.width, dimension));
            }
            else if (fit == "autoH")
            {
                UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
                UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
                // THIS NEEDS A FIX OMG
                // LayoutRebuilder.ForceRebuildLayoutImmediate(RectOptions);
                Canvas.ForceUpdateCanvases();
                UISizeFitterComponent.SetLayoutVertical();
                base.SetDimensions( new Vector2(dimension, RectOptions.rect.height));
            }
        }

        public void RemoveContentSizeFitter()
        {
            var component = UIElement.GetComponent(typeof(ContentSizeFitter)) as ContentSizeFitter;
            if(component != null)
                Object.Destroy(component);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

经过数小时的努力寻找解决方案后,我终于找到了。

这实际上是一个非常愚蠢的错误。

以下是一种解释:

我通过以下方式启动了自定义UIText类:

var Title = new EasyText(new Vector2(390, -20), Vector2.zero, Data.title, 30, _color: new Color(0,0,0,1));

是否注意到Vector.zero的文本元素的尺寸?是的,这会引起一些问题。

因为在刚创建的title元素上我做了以下事情,所以称它为:

Title.SetTextContainerSize("autoH", 330);

这将调用我的尺码拟合器更新函数,如下所示:

public void SetTextContainerSize(string fit, float dimension = 0)
    {
        if (UIElement.GetComponent<ContentSizeFitter>() == null)
            UISizeFitterComponent = UIElement.AddComponent(typeof(ContentSizeFitter)) as ContentSizeFitter;

        if (fit == "autoWH")
        {
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
            base.SetDimensions( RectOptions.sizeDelta);
        }
        else if (fit == "autoW")
        {
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.Unconstrained;
            Canvas.ForceUpdateCanvases();
            base.SetDimensions( new Vector2(RectOptions.rect.width, dimension));
        }
        else if (fit == "autoH")
        {
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
            Canvas.ForceUpdateCanvases();
            base.SetDimensions( new Vector2(dimension, RectOptions.rect.height));
        }
    }

在fit值为autoW或autoH的情况下,程序将添加内容大小拟合器,但是由于初始化的原因,元素的大小为0。内容大小调整器将元素扩展到极限,因为另一个大小仅为0。 然后,我更新画布,但是这没有做任何事情,因为元素的宽度或高度为0。在取回值时会产生大量数字。那么如何解决呢?

在添加内容大小钳工之前,只需确保元素具有一定的宽度或高度,即可:

public void SetTextContainerSize(string fit, float dimension = 0)
    {
        if (UIElement.GetComponent<ContentSizeFitter>() == null)
            UISizeFitterComponent = UIElement.AddComponent(typeof(ContentSizeFitter)) as ContentSizeFitter;

        if (fit == "autoWH")
        {
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
        }
        else if (fit == "autoW")
        {
            base.SetDimensions(new Vector2(dimension, dimension));
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.Unconstrained;
            Canvas.ForceUpdateCanvases();
            base.SetDimensions( new Vector2(RectOptions.rect.width, dimension));
        }
        else if (fit == "autoH")
        {
            base.SetDimensions(new Vector2(dimension, dimension));
            UISizeFitterComponent.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
            UISizeFitterComponent.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
            Canvas.ForceUpdateCanvases();
            base.SetDimensions( new Vector2(dimension, RectOptions.rect.height));
        }
    }

这解决了我的问题。我真的希望这对以后的所有人有帮助!
如果您什么都不懂,请发表评论,以便我澄清我的回答:)