对于滚动类型为“弹性”的ScrollRect的Peter Morris答案的一种变体。我很困扰滚动矩形在边界情况下(前几个或最后几个元素)仍然保持动画效果。希望这有用:
public static IEnumerator BringChildIntoView(this UnityEngine.UI.ScrollRect instance, RectTransform child)
{
Canvas.ForceUpdateCanvases();
Vector2 viewportLocalPosition = instance.viewport.localPosition;
Vector2 childLocalPosition = child.localPosition;
Vector2 result = new Vector2(
0 - (viewportLocalPosition.x + childLocalPosition.x),
0 - (viewportLocalPosition.y + childLocalPosition.y)
);
instance.content.localPosition = result;
yield return new WaitForUpdate();
instance.horizontalNormalizedPosition = Mathf.Clamp(instance.horizontalNormalizedPosition, 0f, 1f);
instance.verticalNormalizedPosition = Mathf.Clamp(instance.verticalNormalizedPosition, 0f, 1f);
}
这会引入一个帧延迟。
更新:这里有一个版本,它不会引入帧延迟,而且还考虑了内容的缩放:
public static void BringChildIntoView(this UnityEngine.UI.ScrollRect instance, RectTransform child)
{
instance.content.ForceUpdateRectTransforms();
instance.viewport.ForceUpdateRectTransforms();
Vector2 viewportLocalPosition = instance.viewport.localPosition;
Vector2 childLocalPosition = child.localPosition;
Vector2 newContentPosition = new Vector2(
0 - ((viewportLocalPosition.x * instance.viewport.localScale.x) + (childLocalPosition.x * instance.content.localScale.x)),
0 - ((viewportLocalPosition.y * instance.viewport.localScale.y) + (childLocalPosition.y * instance.content.localScale.y))
);
instance.content.localPosition = newContentPosition;
Rect contentRectInViewport = TransformRectFromTo(instance.content.transform, instance.viewport);
float deltaXMin = contentRectInViewport.xMin - instance.viewport.rect.xMin;
if(deltaXMin > 0)
{
newContentPosition.x -= deltaXMin;
}
float deltaXMax = contentRectInViewport.xMax - instance.viewport.rect.xMax;
if (deltaXMax < 0)
{
newContentPosition.x -= deltaXMax;
}
float deltaYMin = contentRectInViewport.yMin - instance.viewport.rect.yMin;
if (deltaYMin > 0)
{
newContentPosition.y -= deltaYMin;
}
float deltaYMax = contentRectInViewport.yMax - instance.viewport.rect.yMax;
if (deltaYMax < 0)
{
newContentPosition.y -= deltaYMax;
}
instance.content.localPosition = newContentPosition;
instance.content.ForceUpdateRectTransforms();
}
public static Rect TransformRectFromTo(Transform from, Transform to)
{
RectTransform fromRectTrans = from.GetComponent<RectTransform>();
RectTransform toRectTrans = to.GetComponent<RectTransform>();
if (fromRectTrans != null && toRectTrans != null)
{
Vector3[] fromWorldCorners = new Vector3[4];
Vector3[] toLocalCorners = new Vector3[4];
Matrix4x4 toLocal = to.worldToLocalMatrix;
fromRectTrans.GetWorldCorners(fromWorldCorners);
for (int i = 0; i < 4; i++)
{
toLocalCorners[i] = toLocal.MultiplyPoint3x4(fromWorldCorners[i]);
}
return new Rect(toLocalCorners[0].x, toLocalCorners[0].y, toLocalCorners[2].x - toLocalCorners[1].x, toLocalCorners[1].y - toLocalCorners[0].y);
}
return default(Rect);
}