ContentSizeFitter:它用于自适应对象尺寸,根据ILayoutElement接口的子物体调整自身大小。在使用时要注意,挂载ContentSizeFitter后,大小变化可能需要下一帧生效,可通过调用SetLayoutHorizontal或ForceRebuildLayoutImmediate方法强制更新。
ContentSizeFitter不改变子物体的大小和位置,而是根据子物体(ILayoutElement)来改变自身的尺寸
ContentSizeFitter所挂载的对象上必须挂载了实现ILayoutElement接口的组件
源码解析
FitMode:自适应尺寸适合模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public enum FitMode { Unconstrained, MinSize, PreferredSize }
|
一些字段参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
[SerializeField] protected FitMode m_HorizontalFit = FitMode.Unconstrained; public FitMode horizontalFit { get { return m_HorizontalFit; } set { if (SetPropertyUtility.SetStruct(ref m_HorizontalFit, value)) SetDirty(); } }
[SerializeField] protected FitMode m_VerticalFit = FitMode.Unconstrained; public FitMode verticalFit { get { return m_VerticalFit; } set { if (SetPropertyUtility.SetStruct(ref m_VerticalFit, value)) SetDirty(); } }
[System.NonSerialized] private RectTransform m_Rect; private RectTransform rectTransform { get { if (m_Rect == null) m_Rect = GetComponent<RectTransform>(); return m_Rect; } }
|
生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| protected override void OnEnable() { base.OnEnable(); SetDirty(); }
protected override void OnDisable() { m_Tracker.Clear(); LayoutRebuilder.MarkLayoutForRebuild(rectTransform); base.OnDisable(); }
protected override void OnRectTransformDimensionsChange() { SetDirty(); }
#if UNITY_EDITOR protected override void OnValidate() { SetDirty(); } #endif
|
SetDirty:强制重建布局
1 2 3 4 5 6 7
| protected void SetDirty() { if (!IsActive()) return; LayoutRebuilder.MarkLayoutForRebuild(rectTransform); }
|
SetLayoutHorizontal:计算并将大小的水平分量应用于RectTransform
1 2 3 4 5
| public virtual void SetLayoutHorizontal() { m_Tracker.Clear(); HandleSelfFittingAlongAxis(0); }
|
SetLayoutVertical:计算并将大小的垂直分量应用于RectTransform
1 2 3 4
| public virtual void SetLayoutVertical() { HandleSelfFittingAlongAxis(1); }
|
HandleSelfFittingAlongAxis:设置对象的位置和大小,对象属性直接通过LayoutUtility.GetMinSize与LayoutUtility.GetPreferredSize获取,获取时会从对象自身查找ILayoutElement,获取到minWidth与preferredWidth,如果不存在则返回默认值0
UGUI源码解析——LayoutUtility
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private void HandleSelfFittingAlongAxis(int axis) { FitMode fitting = (axis == 0 ? horizontalFit : verticalFit); if (fitting == FitMode.Unconstrained) { m_Tracker.Add(this, rectTransform, DrivenTransformProperties.None); return; }
m_Tracker.Add(this, rectTransform, (axis == 0 ? DrivenTransformProperties.SizeDeltaX : DrivenTransformProperties.SizeDeltaY));
if (fitting == FitMode.MinSize) rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetMinSize(m_Rect, axis)); else rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, LayoutUtility.GetPreferredSize(m_Rect, axis)); }
|
注意:给对象身上挂载ContentSizeFitter组件后设置PreferredSize后立即获取rectTransform.sizeDelte或rectTransform.rect.size还是之前的值,下一帧后获取才是真实的size,可以使用以下方法执行一次更新方法再去获取rect
1 2 3 4
| GetComponent<ContentSizeFitter>().SetLayoutHorizontal();
LayoutRebuilder.ForceRebuildLayoutImmediate(txt.rectTransform);
|
UGUI源码解析——ContentSizeFitter