【问题标题】:How to make custom Unity LayoutGroup expand to fit contents如何使自定义 Unity LayoutGroup 扩展以适应内容
【发布时间】:2019-06-11 02:35:01
【问题描述】:

在需要垂直调整大小以包含其子项的情况下,我正在尝试使用this question 的答案中描述的自定义 FlowLayoutGroup(也在GitHub 上)。

我的设置如下所示:

  • 可滚动矩形
    • 具有 VerticalLayoutGroup comp(父滚动矩形的内容)的面板应垂直调整大小以适合子级:
      • 具有 FlowLayoutGroup 的面板应垂直调整大小以适合子级
      • 带有 FlowLayoutGroup (2) 的面板也必须调整大小...
      • 等等……

我在 FlowLayoutGroup 中添加了一个内容大小调整器,调整了垂直组的布局子大小控件,但没有成功。

用户可以在应用程序运行时添加和删除组的子项,我希望 UI 做出响应,因此无法提前设置所有内容的高度。

我还查看了统一源代码,试图弄清楚如何自己将其写入组件。这看起来是最好的选择,但由于我是 Unity 和 C# 的新手,所以我花了相当多的时间。希望有人已经解决了类似的问题。

除了 LayoutGroups 调整大小以垂直适合其子项的缺失行为之外,一切都按预期/预期运行。

我该怎么做?

【问题讨论】:

    标签: c# unity3d unity3d-2dtools unity3d-ui


    【解决方案1】:

    经过一段时间和风滚草徽章后,我决定花时间制定解决方案,希望其他人也能从中受益。

    同样,这是the work done here 的修改版本。感谢那。这个组件现在计算它自己的首选大小。

    主要变化:

    1. 我非常严格地剥离了它:
      • 所有水平覆盖都被清空,我只需要水平环绕行为
      • 从 GridLayout 类中删除了一些明显的宿醉变量
    2. 计算子位置和行数的逻辑,首选高度在它自己的方法中。
    3. 子位置存储在 Vector2 数组中,以将计算与子设置分开。

    这解决了整个组件高度不调整的问题,它也立即响应,原始脚本由于设置子 rectTransforms 的方式然后访问脚本需要两个“周期”来识别子的尺寸。

    这适合我的所有需求,我想它也可以很容易地重新加工以处理垂直包装......

    using UnityEngine;
    using UnityEngine.UI;
    
    [AddComponentMenu("Layout/Wrap Layout Group", 153)]
    public class WrapLayoutGroup : LayoutGroup
    {
        [SerializeField] protected Vector2 m_Spacing = Vector2.zero;
        public Vector2 spacing { get { return m_Spacing; } set { SetProperty(ref m_Spacing, value); } }
    
        [SerializeField] protected bool m_Horizontal = true;
        public bool horizontal { get { return m_Horizontal; } set { SetProperty(ref m_Horizontal, value); } }
    
        private float availableWidth { get { return rectTransform.rect.width - padding.horizontal + spacing.x; } }
    
        private const float MIN_HEIGHT = 80;
    
        private int preferredRows = 1;
        private float calculatedHeight = MIN_HEIGHT;
    
        private Vector2[] childPositions = new Vector2[0];
    
        protected WrapLayoutGroup()
        { }
    
    #if UNITY_EDITOR
        protected override void OnValidate()
        {
            base.OnValidate();
        }
    
    #endif
    
        public override void CalculateLayoutInputVertical()
        {
            calculatePositionsAndRequiredSize();
            SetLayoutInputForAxis(calculatedHeight, calculatedHeight, -1, 1);
        }
    
        public override void SetLayoutHorizontal() { }
    
        public override void SetLayoutVertical()
        {
            SetChildren();
        }
    
        private void SetChildren()
        {
            for (int i = 0; i < rectChildren.Count; i++)
            {
                RectTransform child = rectChildren[i];
                SetChildAlongAxis(child, 0, childPositions[i].x, LayoutUtility.GetPreferredWidth(child));
                SetChildAlongAxis(child, 1, childPositions[i].y, LayoutUtility.GetPreferredHeight(child));
            }
        }
    
        private void calculatePositionsAndRequiredSize()
        {
            childPositions = new Vector2[rectChildren.Count];
    
            Vector2 startOffset = new Vector2(
                GetStartOffset(0, 0),
                GetStartOffset(1, 0)
            );
    
            Vector2 currentOffset = new Vector2(
                startOffset.x,
                startOffset.y
            );
    
            float childHeight = 0;
            float childWidth = 0;
            float maxChildHeightInRow = 0;
    
            int currentRow = 1;
    
            for (int i = 0; i < rectChildren.Count; i++)
            {
                childHeight = LayoutUtility.GetPreferredHeight(rectChildren[i]);
                childWidth = LayoutUtility.GetPreferredWidth(rectChildren[i]);
    
                //check for new row start
                if (currentOffset.x + spacing.x + childWidth > availableWidth && i != 0)
                {
                    currentOffset.x = startOffset.x;
                    currentOffset.y += maxChildHeightInRow + spacing.y;
                    currentRow++;
                    maxChildHeightInRow = 0;
                }
    
                childPositions[i] = new Vector2(
                    currentOffset.x,
                    currentOffset.y
                );
    
                //update offset
                maxChildHeightInRow = Mathf.Max(maxChildHeightInRow, childHeight);
                currentOffset.x += childWidth + spacing.x;
    
            }
    
            //update groups preferred dimensions
            preferredRows = currentRow;
            calculatedHeight = currentOffset.y + maxChildHeightInRow + padding.vertical - spacing.y;
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-12
      • 2015-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-25
      • 2015-09-15
      • 2020-08-24
      相关资源
      最近更新 更多