预制结构
脚本挂载Rect上
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// 脚本手动挂载
/// </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>
/// 外部调用
/// </summary>
/// <param name="callBackTemp">条目刷新回调</param>
/// <param name="gridTemp">条目根目录</param>
/// <param name="itemTemp">条目</param>
/// <param name="showLength">初始化条目数</param>
/// <param name="dataLength">数据长度</param>
/// <param name="padHTemp">条目间距</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>
/// 滑动显示变动刷新
/// </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 && 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>
/// 设置数据
/// </summary>
/// <param name="useItem"></param>
/// <param name="index"></param>
private void SetInfo(Transform useItem,int index) {
RectTransform rectTransform = useItem.GetComponent<RectTransform>();
float hight = 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>
/// 获取条目预制
/// </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自定义挂载在条目上
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类
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;
}
}
入口代码
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();
}
}