需求:
如果LayoutGroup的子物体太多,超出layoutGroup的范围,则对子物体进行缩小。确保子物体都在LayoutGroup的范围内
代码:
[ExecuteInEditMode]
[RequireComponent(typeof(HorizontalOrVerticalLayoutGroup))]
public class LayoutGroupChildFitter : MonoBehaviour, ILayoutController
{
[Header("最小缩放尺寸,小于0的话脚本失效")]
public float m_minChildSize = -1f;
[Header("是否为水平布局")]
public bool m_isHorizontal = true;
//layoutGroup
[SerializeField] HorizontalOrVerticalLayoutGroup m_layout = null;
[SerializeField] RectTransform m_rectTransform;
float m_curScale = 0;
//子节点
List<RectTransform> m_rectChildren = new List<RectTransform>();
private void Start()
{
if (m_layout == null)
m_layout = this.transform.GetComponent<HorizontalOrVerticalLayoutGroup>();
if (m_rectTransform == null)
m_rectTransform = this.GetComponent<RectTransform>();
DoFixChildSize();
}
void ILayoutController.SetLayoutHorizontal()
{
if (m_layout == null)
m_layout = this.transform.GetComponent<HorizontalOrVerticalLayoutGroup>();
if (m_rectTransform == null)
m_rectTransform = this.GetComponent<RectTransform>();
DoFixChildSize();
}
void ILayoutController.SetLayoutVertical()
{
if (m_layout == null)
m_layout = this.transform.GetComponent<HorizontalOrVerticalLayoutGroup>();
if (m_rectTransform == null)
m_rectTransform = this.GetComponent<RectTransform>();
DoFixChildSize();
}
///
/// 子节点缩放
///
void DoFixChildSize()
{
if (m_minChildSize < 0) return;
GetRectChildren();
float childrenSize = GetChildrenTotalSize();
float contentSize = GetContentSize();
float scale = contentSize / childrenSize;
scale = Mathf.Clamp(scale, m_minChildSize, 1);
if (m_curScale != scale)
{
Debug.Log($"Layout Child 缩放{contentSize}/{childrenSize}=scale:{scale}");
Vector3 localScale = Vector3.one * scale;
SetChildrenChild(localScale);
m_curScale = scale;
LayoutRebuilder.ForceRebuildLayoutImmediate(m_rectTransform);
}
}
///
/// 把所有子节点设置
///
///
void SetChildrenChild(Vector3 localScale)
{
for (int i = 0; i < m_rectChildren.Count; i++)
{
m_rectChildren[i].localScale = localScale;
}
}
///
/// 计算容器尺寸
///
///
float GetContentSize()
{
float size = (m_isHorizontal) ? m_rectTransform.rect.width : m_rectTransform.rect.height;
//边距
float padding = (m_isHorizontal) ?
m_layout.padding.right + m_layout.padding.left :
m_layout.padding.top + m_layout.padding.bottom;
//总间距
float spacing = (m_rectChildren.Count - 1) * m_layout.spacing;
return size - padding - spacing;
}
///
/// 计算子物体总尺寸
///
///
float GetChildrenTotalSize()
{
//总长度
float total = 0;
for (int i = 0; i < m_rectChildren.Count; i++)
{
if (!m_rectChildren[i].gameObject.activeInHierarchy) continue; //不考虑隐藏
if (m_isHorizontal) total += m_rectChildren[i].sizeDelta.x;
else total += m_rectChildren[i].sizeDelta.y;
}
return total;
}
///
/// 获取子物体
///
void GetRectChildren()
{
if (transform.childCount == m_rectChildren.Count) return;
m_rectChildren.Clear();
for (int i = 0; i < transform.childCount; i++)
{
RectTransform rect = transform.GetChild(i).GetComponent<RectTransform>();
if (!m_rectChildren.Contains(rect)) m_rectChildren.Add(rect);
}
}
}