using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace Ichni.Editor { public class DynamicUISubcontainer : MonoBehaviour { Inspector Inspector => EditorManager.instance.uiManager.inspector; public DynamicUIContainer parentContainer; public RectTransform rect; public List dynamicUIElements; /// 当前行高 [HideInInspector] public float rowHeight = 100f; /// /// 使用 GridLayoutGroup 实现 N 列自动换行布局。 /// 当添加的元素数量超过 elementCountPerRow 时,会自动换行到下一行。 /// public void Initialize(DynamicUIContainer parentContainer, int elementCountPerRow, float height = 100) { this.parentContainer = parentContainer; this.rowHeight = height; int columns = Mathf.Max(1, elementCountPerRow); // ── 启用 GridLayoutGroup ── var grid = GetComponent(); if (grid == null) grid = gameObject.AddComponent(); grid.enabled = true; grid.constraint = GridLayoutGroup.Constraint.FixedColumnCount; grid.constraintCount = columns; grid.childAlignment = TextAnchor.UpperLeft; grid.startCorner = GridLayoutGroup.Corner.UpperLeft; grid.startAxis = GridLayoutGroup.Axis.Horizontal; grid.padding = new RectOffset(10, 10, 0, 0); float spacing = 10f; float totalSpacing = (columns - 1) * spacing; float cellWidth = (LayoutPacker.TotalRowWidth - totalSpacing) / columns; grid.cellSize = new Vector2(cellWidth, height); grid.spacing = new Vector2(spacing, spacing); // ── LayoutElement: preferredHeight = -1 让 GridLayoutGroup 的 ILayoutElement 接管高度 ── var layoutElement = GetComponent(); if (layoutElement == null) layoutElement = gameObject.AddComponent(); layoutElement.preferredHeight = -1; layoutElement.flexibleHeight = -1; // ── ContentSizeFitter: 让子容器高度随网格行数动态增长 ── var fitter = GetComponent(); if (fitter == null) fitter = gameObject.AddComponent(); fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; fitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained; fitter.enabled = true; if (dynamicUIElements == null) dynamicUIElements = new List(); else dynamicUIElements.Clear(); } public DynamicUISubcontainer Mark(string mark, IHaveInspection inspection = null) { inspection ??= Inspector; inspection.MarkedSubcontainers.TryAdd(mark, this); return this; } } }