Unity 列表滚动到指定位置

发布于:2025-03-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

使用场景

策划提出需求:当玩家打开领奖界面时,奖励列表需要自动滑动到可以领奖的奖励栏处或者正在进行的任务栏处。

思路

1、将Content设置好对齐方式和锚点

子物体的预制体和Content:pivot轴心点设置为(0,1),并且设置为左上角对齐。

2、主要根据索引计算Content需要设置的高度即(RectTransform的PosY)

 var sumHeight = targetIndex * (itemHeight + spacing);
 scrollRect.content.anchoredPosition = new Vector2(0, sumHeight);

特殊情况

第一种  子物体较少的情况(Content高度小于可视区域高度)

不用移动,不必处理

第二种 滑动到末尾几个索引的时候

1、需要提前计算viewport可以最多完整囊括多少个子物体(visualCount)

2、如果需要定位的目标索引大于或等于(总数量 - visualCount+1)时,使用

scrollRect.normalizedPosition = new Vector2(0, 0);

 直接滑到底端就行。

代码

using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    public int sumCount;
    public Transform root;
    public GameObject item;
    public ScrollRect scrollRect;
    public float itemHeight;
    public float spacing;//子物体之间的间隔
    public float contentHeight;
    public float viewportHeight;

    public int visualCount;
    public int compareCount;
    
    public InputField inputField;
    
    void Start()
    {
        sumCount = 100;
        spacing = 10;
        
        var itemRect = item.GetComponent<RectTransform>();
        itemHeight = itemRect.rect.height;
        
        for (var i = 1; i <= sumCount; i++)
        {
            var obj = Instantiate(item, root.transform);
            var txtObj = obj.transform.Find("txt");
            var txt = txtObj.GetComponent<Text>();
            txt.text = i.ToString();
        }
        LayoutRebuilder.ForceRebuildLayoutImmediate(scrollRect.content);
        contentHeight = scrollRect.content.rect.height;
        viewportHeight = scrollRect.viewport.rect.height;

        visualCount = (int)(viewportHeight / itemHeight);
        compareCount = sumCount - visualCount + 1;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            var index = int.Parse(inputField.text);
            ScrollToTarget(index);
        }
    }
    
    public void ScrollToTarget(int index)
    {
        if (index <= 0 || index > sumCount)
        {
            return;
        }
        
        //第一种 子物体较少的情况(Content高度小于可视区域高度)
        if (contentHeight < viewportHeight)
        {
            return;
        }   
        
        //先停止列表滑动,以防造成误差
        scrollRect.StopMovement();
        //第二种 滑动到末尾几个索引的时候
        if (index >= compareCount)
        {
            scrollRect.normalizedPosition = new Vector2(0, 0);
            return;
        }
        var targetIndex = index - 1;
        targetIndex = targetIndex < 0 ? 0 : targetIndex;
        var sumHeight = targetIndex * (itemHeight + spacing);
        scrollRect.content.anchoredPosition = new Vector2(0, sumHeight);
    }
}

补充

1、如果需要添加滚动动画,可以使用Dotween来实现

 var sumHeight = targetIndex * (itemHeight + spacing);
 scrollRect.content.DOAnchorPosY(sumHeight,0.5f);