如何使自定义Unity LayoutGroup扩展以适合内容 [英] How to make custom Unity LayoutGroup expand to fit contents

查看:914
本文介绍了如何使自定义Unity LayoutGroup扩展以适合内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用自定义FlowLayoutGroup,如这个问题(也在 GitHub 上)需要垂直调整大小以容纳孩子的情况.

I am attempting to use a custom FlowLayoutGroup as described in the answers of this question ( also up on GitHub) in a situation where it needs to resize vertically to contain it's children.

我的设置如下:

  • ScrollableRect
    • 具有VerticalLayoutGroup comp(父scrollrect的内容)的面板,应垂直调整大小以适合子代:
      • 具有FlowLayoutGroup的面板应垂直调整大小以适合孩子
      • 具有FlowLayoutGroup(2)的面板还必须调整大小...
      • 等...
      • ScrollableRect
        • Panel with VerticalLayoutGroup comp (content of parent scrollrect) that should resize vertically to fit children:
          • Panel with FlowLayoutGroup that should resize vertically to fit children
          • Panel with FlowLayoutGroup (2) also must resize...
          • etc...

          我向FlowLayoutGroup添加了一个内容大小调整器,调整了垂直组的布局子尺寸控制,但没有成功.

          I have added a content size fitter to the FlowLayoutGroup, tweaked the layout child size controls of the vertical group, but with no success.

          用户可以在应用程序运行时添加和删除组的子级,并且我希望UI能够响应,因此无法预先设置所有项目的高度.

          The user may add and remove children of the groups while the app is running and I want the UI to respond so it is not possible to set the height of everything in advance.

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

          I have also looked in the unity source code to try and figure out how to write this into the component myself. This is looking the best bet but taking me considerable time as I'm new to Unity and C#. Hoping someone has solved a similar problem already.

          除了LayoutGroups调整为垂直适合其子级的大小的缺失行为之外,所有功能均按预期/预期运行.

          Everything functions as desired/expected except for the missing behaviour of LayoutGroups resizing to fit their children vertically.

          我该怎么做?

          推荐答案

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

          After some time and a tumbleweed badge I've decided to put the time in to make a solution, hopefully someone else benefits too.

          同样,这是的修改版本.感谢那.现在,此组件将计算自己的首选大小.

          Again, this is a modified version of the work done here. Thanks for that. This component now computes it's own preferred size.

          主要更改:

          1. 我非常认真地将其剥离:
            • 所有水平替换都被清空,我只需要水平包装行为
            • 从GridLayout类中删除了一些明显的宿醉变量
          1. I stripped it back quite severely:
            • All horizontal overrides are emptied, I only need the horizontal wrapping behaviour
            • Removed some apparent hangover variables from GridLayout class

          这解决了整个组件的高度不可调的问题,它还立即响应,使用原始脚本,因为设置了rectTransforms子代,然后访问该脚本的方式花费了两个周期"来识别子代的尺寸.

          This fixes the problem of height of the entire component not adjusting, it also immediately responds, with the original script because of the way children rectTransforms were set then accessed the script took two 'cycles' to recognize the dimensions of a child.

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

          This suits all my needs, I imagine it can be fairly easily reworked to handle vertical wrap too...

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

          这篇关于如何使自定义Unity LayoutGroup扩展以适合内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆