【Unity】UGUI中 Scrollview / ScrollRect滑动到指定元素位置

直接上代码,下面是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~

要实现Unity UGUIScrollView滑动放大,其他的缩小,可以按照以下步骤进行操作: 1. 创建一个ScrollView,用于显示内容,并设置合适的大小和位置。 2. 在ScrollView创建一个Content对象,用于放置所有需要显示的子对象,并设置Layout Group组件,以确保内容按照一定的布局排列。 3. 在每个子对象上添加一个自定义的脚本,用于控制子对象的缩放和位置。脚本需要包含以下几个要点: a. 监听ScrollView滑动事件,获取当前的滑动位置。 b. 根据当前滑动位置,计算每个子对象在滑动过程应该设置的缩放比例。例如,距离居的子对象应该更大,而距离边缘的子对象应该更小。 c. 根据计算得到的缩放比例,分别对每个子对象进行缩放设置。可以使用RectTransform的scale属性来实现缩放功能。 d. 根据子对象的缩放比例和位置信息,将子对象移动到ScrollView的合适位置。可以使用RectTransform的anchoredPosition属性来实现位置调整。 e. 可以根据需要,在脚本添加其他的功能,例如点击子对象时的反应等。 4. 将自定义的脚本添加到所有的子对象上,确保每个子对象都能根据滑动进行缩放和位置调整。 通过以上步骤,我们可以实现在Unity UGUIScrollView滑动过程,距离居的子对象放大,而距离边缘的子对象缩小的效果。具体的缩放比例和位置调整可以根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值