直接上代码,下面是ScrollRect的扩展方法
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public static class ScrollRectExtensions
{
// ScrollRect滚动到指定位置
public static void ScrollToItem(this ScrollRect scrollRect, int itemIndex, float duration = 0f)
{
// 延迟执行,避免列表还没有准备好时执行。
scrollRect.StartCoroutine(ScrollToItemCoroutine(scrollRect, itemIndex, duration));
}
private static IEnumerator ScrollToItemCoroutine(ScrollRect scrollRect, int itemIndex, float duration = 0f)
{
// 等待列表准备好。
yield return new WaitForFixedUpdate(); // 等待一次物理更新,确保列表已准备好。
float normalizedPosition = itemIndex / (float)(scrollRect.content.childCount - 1);
Vector2 targetPosition = new Vector2(scrollRect.horizontalNormalizedPosition, scrollRect.verticalNormalizedPosition);
if (scrollRect.horizontal)
{
targetPosition.x = CalculateHorizontalPosition(scrollRect, normalizedPosition);
}
else if (scrollRect.vertical)
{
targetPosition.y = CalculateVerticalPosition(scrollRect, normalizedPosition);
}
Vector2 startPosition = new Vector2(scrollRect.horizontalNormalizedPosition, scrollRect.verticalNormalizedPosition);
float elapsedTime = 0f;
while (elapsedTime < duration)
{
float normalizedTime = elapsedTime / duration;
scrollRect.normalizedPosition = Vector2.Lerp(startPosition, targetPosition, normalizedTime);
elapsedTime += Time.fixedDeltaTime;
yield return null; // 等待下一帧。
}
scrollRect.normalizedPosition = targetPosition;
}
private static float CalculateHorizontalPosition(ScrollRect scrollRect, float normalizedPosition)
{
float viewportWidth = scrollRect.viewport.rect.width;
float contentWidth = scrollRect.content.sizeDelta.x;
float paddingWidth = scrollRect.padding().left + scrollRect.padding().right;
float spacingWidth = (scrollRect.content.childCount - 1) * scrollRect.spacing();
float totalWidth = contentWidth + paddingWidth + spacingWidth;
float scrollWidth = totalWidth - viewportWidth;
float scrollPosition = normalizedPosition * scrollWidth;
float normalizedScrollPosition = scrollPosition / scrollWidth;
return normalizedScrollPosition;
}
private static float CalculateVerticalPosition(ScrollRect scrollRect, float normalizedPosition)
{
float viewportHeight = scrollRect.viewport.rect.height;
float contentHeight = scrollRect.content.sizeDelta.y;
float paddingHeight = scrollRect.padding().top + scrollRect.padding().bottom;
float spacingHeight = (scrollRect.content.childCount - 1) * scrollRect.spacing();
float totalHeight = contentHeight + paddingHeight + spacingHeight;
// Debug.Log("contentHeight: " + contentHeight + " paddingHeight: " + paddingHeight + " spacingHeight: " + spacingHeight + " totalHeight: " + totalHeight + " viewportHeight: " + viewportHeight);
float scrollHeight = totalHeight - viewportHeight;
float scrollPosition = normalizedPosition * scrollHeight;
float normalizedScrollPosition = scrollPosition / scrollHeight;
return normalizedScrollPosition;
}
// 根据水平或垂直组件获取spacing
public static float spacing(this ScrollRect scrollRect)
{
if (scrollRect.horizontal)
{
return scrollRect.content.GetComponent<HorizontalLayoutGroup>().spacing; // 水平布局的spacing是水平方向的间距。
}
else if (scrollRect.vertical)
{
return scrollRect.content.GetComponent<VerticalLayoutGroup>().spacing; // 垂直布局的spacing是垂直方向的间距。
}
return 0f;
}
// 根据水平或垂直组件获取padding
public static RectOffset padding(this ScrollRect scrollRect)
{
if (scrollRect.horizontal)
{
return scrollRect.content.GetComponent<HorizontalLayoutGroup>().padding; // 水平布局的padding是水平方向的间距。
}
else if (scrollRect.vertical)
{
return scrollRect.content.GetComponent<VerticalLayoutGroup>().padding; // 垂直布局的padding是垂直方向的间距。
}
return new RectOffset(0, 0, 0, 0); // 如果没有水平或垂直组件,则返回默认的RectOffset。
}
}
下面是调用方法:
ScrollRect.ScrollToItem( index, 0.5f);
其中index为该元素在scrollview中的第几位, 0.5f为延时,该扩展方法主要针对scrollview下面带有自动排列位置的组件HorizontalLayoutGroup和VerticalLayoutGroup,没有也可以用。
over~