在编辑器中,通过设置Raw edit mode,可以切换两种,元素锚点的改变模式:
- 一种是锚点单独改变,即:不开启原始模式,保持原样,改变anchoredPosition与sizeDelta。
- 一种是锚点联动显示,即:开启原始模式,不保持原样,不改变anchoredPosition与sizeDelta。
原理很简单,anchoredPosition与sizeDelta都是相对于锚点Anchor的,所以Anchor变动,元素rect保持原样,就需要改变pos和delta,而元素rect跟着变动,就可以维持pos和delta不变。
那么,在运行时用代码设置anchorMin与anchorMax,只有联动显示的模式,即相当于开启原始模式——不改变anchoredPosition与sizeDelta,改变元素rect的显示。
但有时候,我们需要只改变锚点,而保持rect显示不变——这是利用锚点适配不同分辨率后的结果——这样其父类的改变,就可以不影响子类的缩放,如:将子类锚点设置为中心点。
解决方案,就是用offsetMin与offsetMax,来反向抵消anchorMin与anchorMax的变化,从而维持元素rect的显示不变。
代码实现如下:
/// <summary>
/// Set the anchorMin [v2] without changing the [rectTransform] display.
/// Assume [rectTransform] has a parent, because the root is rarely operated on.
/// </summary>
public static void SetAnchorMinOnly(this RectTransform rectTransform, in Vector2 v2)
{
var offsetOriginal = rectTransform.anchorMin - v2;
if (offsetOriginal == Vector2.zero)
{
Debug.LogWarning($"[SetAnchorMinOnly]: The [v2 = {v2}] is the same as the [anchorMin].");
return;
}
else if (offsetOriginal.x == 0.0f)
{
Debug.LogWarning($"[SetAnchorMinOnly]: The [v2.x = {v2.x}] is the same as the [anchorMin.x].");
rectTransform.SetAnchorMinYOnly(v2.y);
return;
}
else if (offsetOriginal.y == 0.0f)
{
Debug.LogWarning($"[SetAnchorMinOnly]: The [v2.y = {v2.y}] is the same as the [anchorMin.y].");
rectTransform.SetAnchorMinXOnly(v2.x);
return;
}
rectTransform.anchorMin = v2;
var parentSize = (rectTransform.parent as RectTransform).rect.size;
rectTransform.offsetMin = parentSize * offsetOriginal;
}
/// <summary>
/// Set the anchorMax [v2] without changing the [rectTransform] display.
/// Assume [rectTransform] has a parent, because the root is rarely operated on.
/// </summary>
public static void SetAnchorMaxOnly(this RectTransform rectTransform, in Vector2 v2)
{
var offsetOriginal = rectTransform.anchorMax - v2;
if (offsetOriginal == Vector2.zero)
{
Debug.LogWarning($"[SetAnchorMaxOnly]: The [v2 = {v2}] is the same as the [anchorMax].");
return;
}
else if (offsetOriginal.x == 0.0f)
{
Debug.LogWarning($"[SetAnchorMaxOnly]: The [v2.x = {v2.x}] is the same as the [anchorMax.x].");
rectTransform.SetAnchorMaxYOnly(v2.y);
return;
}
else if (offsetOriginal.y == 0.0f)
{
Debug.LogWarning($"[SetAnchorMaxOnly]: The [v2.y = {v2.y}] is the same as the [anchorMax.y].");
rectTransform.SetAnchorMaxXOnly(v2.x);
return;
}
rectTransform.anchorMax = v2;
var parentSize = (rectTransform.parent as RectTransform).rect.size;
rectTransform.offsetMax = parentSize * offsetOriginal;
}