Получить высоту текстового элемента пользовательского интерфейса не правильно Unity - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть код для установки пользовательского элемента для текстового элемента, а затем высота настраивается автоматически следующим образом:

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 голосов
/ 10 сентября 2018

потратив часы на поиски решения, я наконец нашел его.

Это была действительно очень глупая ошибка.

Вот объяснение:

Я инициировал свой пользовательский класс UIText следующим образом:

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

Обратите внимание на Vector.zero для размеров текстового элемента? да, это вызовет некоторые проблемы.

Поскольку следующее, что я сделал, было вызвано, для только что созданного элемента заголовка:

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

В случаях, когда значение подгонки равно 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));
        }
    }

и это решило мою проблему. Я действительно надеюсь, что это поможет кому-нибудь в будущем!
Если вы ничего не понимаете, оставьте комментарий, чтобы я мог уточнить мой ответ:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...