这个主要就展示列表的代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class InfinitySV : MonoBehaviour
{
private RectTransform content;
//item的宽和高
private Vector2 cellsize;
//item之间的间距
private Vector2 spacingsize;
//上下左右间距
private RectOffset rectoffset;
private int index;
public int totalNumberItem
{
set
{
index = value;
}
get
{
return index;
}
}
//存储gameobject对象
private GameObject[] arrayCurrent = null;
//存储显示的对象
private List<GameObject> listItem = new List<GameObject>();
//标记上一次的位置
private int cacheOld = -1;
//显示的行数
private int itemGenerate;
//item对象
private GameObject itemObj;
private bool isInit = false;
//添加item点击事件
private UnityEvent events = new UnityEvent();
//列数
private int constraintCount = 1;
private GameObject funObj;
Dictionary<int, string> data = new Dictionary<int, string>();
// Start is called before the first frame update
void Start()
{
transform.GetComponent<ScrollRect>().onValueChanged.AddListener(Sc);
content = transform.Find("Viewport/Content").GetComponent<RectTransform>();
cellsize = content.gameObject.transform.GetComponent<GridLayoutGroup>().cellSize;
spacingsize = content.gameObject.transform.GetComponent<GridLayoutGroup>().spacing;
constraintCount = content.gameObject.transform.GetComponent<GridLayoutGroup>().constraintCount;
itemGenerate =(Mathf.CeilToInt(transform.GetComponent<RectTransform>().sizeDelta.y / cellsize.y)+1)* constraintCount;
rectoffset = content.gameObject.transform.GetComponent<GridLayoutGroup>().padding;
}
//开始加载数据
public void SetUp()
{
if (itemObj == null)
{
return;
}
int totalHeight = (int)((totalNumberItem / constraintCount+1) * (cellsize.y+spacingsize.y))+rectoffset.top+rectoffset.bottom;
content.sizeDelta = new Vector2(content.sizeDelta.x, totalHeight);
arrayCurrent = new GameObject[totalNumberItem];
for (int i = 0; i < itemGenerate; i++)
{
GameObject obj = null;
if (!isInit)
{
if (i < totalNumberItem)
{
obj = GameObject.Instantiate(itemObj) as GameObject;
obj.name = "item_" + (i);
obj.transform.SetParent(content.transform, false);
obj.transform.localScale = Vector3.one;
listItem.Add(obj);
RectTransform rect = obj.GetComponent<RectTransform>();
if (rect != null)
{
Vector2 anchor = rect.pivot;
rect.pivot = new Vector2(anchor.x, 1);
}
}
Reload(obj, i);
arrayCurrent[i] = obj;
}
else
{
if (i < totalNumberItem)
{
obj = listItem[i];
obj.SetActive(true);
Reload(obj, i);
arrayCurrent[i] = obj;
}
else
{
obj = listItem[i];
obj.SetActive(false);
}
}
}
isInit = true;
}
//修改item的位置信息
protected virtual void Reload(GameObject obj, int indexReload)
{
obj.transform.name = "item_" + indexReload;
Vector3 vec = Vector3.zero;
vec = new Vector2(0, 0);
vec = GetLocationAppear(vec, indexReload);
obj.transform.localPosition = vec;
}
private Vector3 GetLocationAppear(Vector2 initVec, int location)
{
Vector3 vec = initVec;
int vHeath = location / constraintCount;
int vLength = location % constraintCount;
vec = new Vector3(rectoffset.left+ (- cellsize.x)+(cellsize.x+spacingsize.x)* vLength, (-cellsize.y - spacingsize.y) * vHeath+ rectoffset.top, 0);
return vec;
}
public void RefreshUI(GameObject obj, Dictionary<int,string>data)
{
itemObj = obj;
totalNumberItem = data.Count;
this.data = data;
}
//滑动条的监听事件
public void Sc(Vector2 vec)
{
if (arrayCurrent.Length < 1)
{
return;
}
//获取第一个显示的id
int index = GetItemID();
//判断是否与上一次显示相同
if (cacheOld != index)
{
cacheOld = index;
}
else
{
return;
}
if (!FixFastReload(index))
{
GameObject objIndex = arrayCurrent[index];
if (objIndex == null)
{
//向上滑动
//原理与向下滑动相反
int next = index + itemGenerate;
if (next > totalNumberItem - 1)
{
return;
}
else
{
GameObject objNow = arrayCurrent[next];
if (objNow != null)
{
arrayCurrent[next] = objIndex;
arrayCurrent[index] = objNow;
Reload(arrayCurrent[index], index);
}
}
}
else
{
//向下滑动
//例如现在是显示3-10,接下来是显示4-11,所以要把之前显示3的item对象给新的11使用,然后将显示3的对象为null
if (index > 0)
{
GameObject obj = arrayCurrent[index - 1];
if (obj == null)
{
return;
}
int next = index - 1 + itemGenerate;
if (next > totalNumberItem - 1)
{
return;
}
else
{
GameObject objNow = arrayCurrent[next];
if (objNow == null)
{
arrayCurrent[next] = obj;
arrayCurrent[index - 1] = objNow;
Reload(arrayCurrent[next], next);
}
}
}
}
}
}
//获取第一个显示的ID
private int GetItemID()
{
int index = (int)(content.anchoredPosition.y / cellsize.y)*constraintCount;
if (index < 0)
index = 0;
if (index > totalNumberItem - 1)
{
index = totalNumberItem - 1;
}
return index;
}
//判断是否之前获取的对象
public bool FixFastReload(int index)
{
bool isNeedFix = false;
int add = index + 1;
for (int i = add; i < index + itemGenerate; i++)
{
if (i < totalNumberItem)
{
GameObject obj = arrayCurrent[i];
if (obj == null)
{
isNeedFix = true;
break;
}
}
}
if (isNeedFix)
{
for (int i = 0; i < totalNumberItem; i++)
{
arrayCurrent[i] = null;
}
int start = index;
if (start + itemGenerate > totalNumberItem)
{
start = totalNumberItem - itemGenerate;
}
for (int i = 0; i < itemGenerate; i++)
{
arrayCurrent[start + i] = listItem[i];
Reload(arrayCurrent[start + i], start + i);
}
return true;
}
return false;
}
}
其实它的原理就是通过获取content的长度除于格子的高度,来得到第一个显示的格式的id号,如果调用就是
for (int i = 0; i < 100; i++)
{
Data.Add(i, i.ToString());
}
sv.RefreshUI(item, Data);
sv.SetUp();
可能这些毕竟简单的弄了一下,扩展的东西有很多方面,后期会找个时间去优化一下。