Unity Simple Loop List

prefabricated structure

The script is mounted on Rect

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine. EventSystems;
using UnityEngine.UI;
/// <summary>
/// Script to mount manually
/// </summary>
public class ScrollListLoop: MonoBehaviour
{
    private int padH;
    private int recordOperateIndex;
    private int dataLength;
    private int operateIndex = 0;
    private int showLenth;
    private Transform grid;
    private Transform item;
    private RectTransform rectTransformGrid;
    private RectTransform rectTransformItem;
    private ScrollRect rectSroll;
    private Action<Transform, int> callBack;
    private List<Transform> itemListPool;
    private List<ItemIndex> nowShowData=new List<ItemIndex>();
    private List<ItemIndex> freeItem = new List<ItemIndex>();
    private List<int> needShowIndex = new List<int>();
    /// <summary>
    /// External call
    /// </summary>
    /// <param name="callBackTemp">Entry refresh callback</param>
    /// <param name="gridTemp">entry root directory</param>
    /// <param name="itemTemp">entry</param>
    /// <param name="showLength">Number of initialization entries</param>
    /// <param name="dataLength">data length</param>
    /// <param name="padHTemp">entry spacing</param>
    public void Init(Action<Transform,int> callBackTemp,Transform gridTemp, Transform itemTemp,int showLength ,int dataLength,int padHTemp=10)
    {
        grid = gridTemp;
        item = itemTemp;
        padH = padHTemp;
        callBack = callBackTemp;
        rectSroll = gameObject. GetComponent<ScrollRect>();
        rectSroll.onValueChanged.AddListener(ScrollRectIng);

        rectTransformGrid = grid. GetComponent<RectTransform>();
        rectTransformItem = item. GetComponent<RectTransform>();
        rectTransformGrid.sizeDelta = new Vector2(rectTransformGrid.sizeDelta.x, rectTransformItem.sizeDelta.y * dataLength + padH * (dataLength - 1));

        this. showLenth = showLength;
        this.dataLength = dataLength;
        for (int i = 0; i < showLength; i ++ )
        {
            Transform needItem = GetItem();

            nowShowData. Add(needItem. GetComponent<ItemIndex>());
            SetInfo(needItem, i);
        }

    }
    /// <summary>
    /// Swipe to display changes and refresh
    /// </summary>
    private void UpdateShowData() {
        needShowIndex. Clear();
        freeItem. Clear();
        for (int i = operateIndex; i < showLenth + operateIndex; i ++ )
        {
            if (!IsExist(i))
            {
                needShowIndex. Add(i);
            }
        }
        for (int i = 0; i < nowShowData. Count; i ++ )
        {
            if (!IsExistItemIndex(nowShowData[i].Index))
            {
                freeItem.Add(nowShowData[i]);
            }
        }
        if (needShowIndex.Count != 0 & amp; & amp; freeItem.Count != 0) {
            for (int i = 0; i < needShowIndex. Count; i ++ )
            {
                ItemIndex itemIndex = freeItem[0];
                freeItem. RemoveAt(0);
                SetInfo(itemIndex. transform, needShowIndex[i]);
            }
        }
    }
    private bool IsExist(int index) {
        for (int i = 0; i < nowShowData. Count; i ++ )
        {
            if (nowShowData[i].Index == index)
                return true;
        }
        return false;
    }
    private bool IsExistItemIndex(int index) {
        for (int i = operateIndex; i < showLenth + operateIndex; i ++ )
        {
            if (i == index)
                return true;
        }
        return false;
    }
    private void ScrollRectIng(Vector2 pos) {
        Vector2 gridPos = rectTransformGrid. anchoredPosition;
        float itemH = item.GetComponent<RectTransform>().sizeDelta.y;
        operateIndex =(int)Mathf.Floor(gridPos.y/(itemH + padH));
        operateIndex = operateIndex < 0 ? 0 : operateIndex;
        operateIndex = operateIndex > dataLength - showLenth ? dataLength - showLenth : operateIndex;
        if (recordOperateIndex != operateIndex) {
            UpdateShowData();
            recordOperateIndex = operateIndex;
        }
    }
    /// <summary>
    /// set data
    /// </summary>
    /// <param name="useItem"></param>
    /// <param name="index"></param>
    private void SetInfo(Transform useItem, int index) {
        RectTransform rectTransform = useItem. GetComponent<RectTransform>();
        float height = rectTransform.sizeDelta.y;
        float h = 0;
        if (index > 0) {
            h = index * (hight + padH);
        }
        rectTransform.anchoredPosition = new Vector2(0,-h);

        ItemIndex itemIndex = useItem. GetComponent<ItemIndex>();
        itemIndex. SetIndex(index);
        callBack(useItem, index);
    }
    /// <summary>
    /// Get item prefab
    /// </summary>
    /// <returns></returns>
    private Transform GetItem() {
        if (itemListPool == null) {
            itemListPool = new List<Transform>();
        }
        Transform useItem = itemListPool.Count==0?null:itemListPool[0];
        if (useItem==null) {
            Transform t=Instantiate(item);
            ItemIndex itemIndex = t.GetComponent<ItemIndex>();///index custom mounted on the item
            if (itemIndex == null) {
                t.gameObject.AddComponent<ItemIndex>();
            }
            itemListPool. Add(t);
            t. SetParent(grid);
        }
        useItem = itemListPool[0];
        itemListPool. RemoveAt(0);

        useItem.gameObject.SetActive(true);
        return useItem;
    }
}

ItemIndex class

using System. Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemIndex : MonoBehaviour
{
    private int index;
    public int Index {
        get { return index; }
    }
    public void SetIndex(int index) {
        this. index = index;
    }
}

entry code

using System. Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MainList : MonoBehaviour
{
    private ScrollListLoop scrollListLoop;
    public Transform grid;
    public Transform item;
    List<int> list;
    // Start is called before the first frame update
    void Start()
    {
        list = new List<int>();
        for (int i = 1; i <= 20; i ++ )
        {
            list.Add(i);
        }
        scrollListLoop = transform. gameObject. AddComponent<ScrollListLoop>();
        scrollListLoop.Init(SetInfo, grid, item , 10, list.Count);
    }
    void SetInfo(Transform item, int index) {
        Text text = item. Find("Text"). GetComponent<Text>();
        text.text = list[index].ToString();
    }
}