这篇文章主要为大家详细介绍了UGUI实现ScrollView无限滚动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
抽空做了一个UGUI的无限滚动的效果。只做了一半(向下无限滚动)。网上也看了很多教程,感觉还是按照自己的思路来写可能比较好。搭建如下:
content节点不添加任何组件。布局组件默认是会重新排版子节点的,所以如果子节点的位置变化,会重新排版,不能达到效果。Size Fitter组件也不加,自己写代码调整Size大小(不调整大小,无法滑动)。
最主要的实现过程就是用Queue来搬运Cell。在向下滚动的过程中(鼠标上滑),顶部滑出View Port的Cell被搬运到底部续上。这点类似于Queue的先见先出原则,再把Dequeue出来的元素添加到末尾,就很类似于ScrollView的无限滚动的原理了。在鼠标上滑的过程中,content的PosY值是一直增加的,所以触发滚动的条件就可以设定为位移之差大于Cell的高度值即可。
数据的刷新,数据到头之后,不能再次进行滚动轮换了,这里用一组值来记录初始化的一组Cell显示的是数据的哪一段。例如HeadNum和TaiNum。比如用20个Cell显示100条数据。初始化后,HeadNum就是0,TailNum就是19。上滑一行数据后,HeadNum=4,TailNum=23(这里假设是20个Cell排成4列)。
下面是完整代码:
public class UIScrollViewTest : MonoBehaviour {
public RectTransform content;
public GameObject cell;
// cell的初始化个数
public int cellAmount = 0;
// 鼠标上滑时,存储Cell的Queue。正序存储
public Queue F_cellQuee = new Queue();
// 鼠标下滑时,存储Cell的Queue。到序存储
public Queue B_cellQuee = new Queue();
// cell的Size
public Vector2 cellSize = new Vector2(100,100);
// cell的间隔
public Vector2 cellOffset = new Vector2(0,0);
// 列数
public int columnCount = 0;
private int rowCount;
// 上一次content的位置
public float lastPos;
// 滚动的次数
public int loopCount = 0;
// cell显示的数据段的开头和结尾序号
public int HeadNum = 0;
public int TailNum;
public Sprite[] sp;
public List<Sprite> data;
void Start()
{
for (int i = 0; i < sp.Length; i++)
{
data.Add(sp[i]);
}
InitialScrollView(data);
TailNum = cellAmount-1;
lastPos = content.localPosition.y;
//Debug.LogError("行数是:::" + rowCount);
//Debug.LogError("+++++++++++++++++ " + (5>>3));
}
void Update()
{
// 触发滚动。
if (content.localPosition.y - lastPos > cellSize.y && data.Count - cellAmount - loopCount*columnCount >0)
{
//Debug.LogError("11111111111 " + (data.Count - cellAmount - loopCount * columnCount));
LoopScrolView(data);
lastPos = content.localPosition.y;
}
}
// 初始化cell
void InitialScrollView(List<Sprite> data)
{
for (int i = 0; i < cellAmount; i++)
{
GameObject obj = Instantiate(cell.gameObject);
obj.transform.SetParent(content);
obj.name = "cell0" + i.ToString();
obj.transform.GetChild(0).GetComponent<Text>().text = "cell0"+i.ToString();
// 显示默认的数据
obj.GetComponent<Image>().sprite = data[i];
}
// 初始化Queue
for (int i = content.childCount-1; i >= 0; i--)
{
B_cellQuee.Enqueue(content.GetChild(i).gameObject);
}
for (int i = 0; i < content.childCount; i++)
{
F_cellQuee.Enqueue(content.GetChild(i).gameObject);
}
// 计算行数
if (cellAmount % columnCount >0)
{
rowCount = cellAmount / columnCount + 1;
} else {
rowCount = cellAmount / columnCount;
}
// 排列cell的位置
int index = 0;
for (int r = 1; r <= rowCount; r++)
{
for (int c = 1; c <= columnCount; c++)
{
if (index < cellAmount)
{
Vector2 pos = new Vector2(cellSize.x / 2 + (cellSize.x + cellOffset.x) * (c-1), -cellSize.y / 2 - (cellOffset.y + cellSize.y) * (r-1));
content.GetChild(index).GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 0, 100);
content.GetChild(index).GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 0, 100);
content.GetChild(index).GetComponent<RectTransform>().anchoredPosition = pos;
index++;
}
}
}
Vector2 v = content.sizeDelta;
// 初始化content的size
content.sizeDelta = new Vector2(v.x, rowCount * cellSize.y + cellOffset.y*(rowCount-1));
}
/// 保持content的大小,这里是保持大小为在cell的行数基础上,向下多出bottomCount行的距离
void SetContentSize(int upperCount, int bottomCount)
{
if (content.sizeDelta != new Vector2(content.sizeDelta.x, content.sizeDelta.y + bottomCount * (cellSize.y + cellOffset.y)))
{
content.sizeDelta = new Vector2(content.sizeDelta.x, content.sizeDelta.y + bottomCount*(cellSize.y + cellOffset.y));
}
}
// 计算顶部的Cell轮换到底部时的位置。以当前最后一行的最后一个Cell的位置为基准计算。
void SetBottomCellPosition(int index, RectTransform rect, Vector2 pos)
{
Vector2 v = Vector2.zero;
if (cellAmount % columnCount == 0) // 整除。每一行都满的情况。
{
float x = pos.x - cellSize.x * (columnCount - index-1) - cellOffset.x * (columnCount-index-1);
float y = pos.y - cellSize.y - cellOffset.y;
v = new Vector2(x,y);
}
// 出现不满行的情况。例如数据有103个,可以用23个cell来轮换。这样就会出现不满行的情况。
// 这种情况下是顶部的一行cell顺次接到底部不满的行。例如23号cell后面接1号和2号cell,3号和4号cell填充到第“7”行
else if (cellAmount % columnCount + index+1<=columnCount)
{
float x = pos.x + cellSize.x * (index+1) + cellOffset.x * (index+1);
float y = pos.y;
v = new Vector2(x, y);
}
else
{
float x = pos.x - cellSize.x * (columnCount - index-1) - cellOffset.x * (columnCount - index-1);
float y = pos.y - cellSize.y - cellOffset.y;
v = new Vector2(x, y);
}
//Debug.LogError("++++++++++++++ " + pos+ " "+ v);
rect.anchoredPosition = v;
rect.SetAsLastSibling();
}
// 计算底部的cell轮换到顶部是的位置,基准位置是当前行的第一个cell。
void SetUpperCellPosition(int index, RectTransform rect, Vector2 pos)
{
Vector2 v = Vector2.zero;
if (cellAmount % columnCount == 0) // 整除
{
float x = pos.x + cellSize.x * index + cellOffset.x * index;
float y = pos.y + cellSize.y + cellOffset.y;
v = new Vector2(x, y);
}
//else if (cellAmount % columnCount + index + 1 <= columnCount)
//{
// float x = pos.x + cellSize.x * (index + 1) + cellOffset.x * (index + 1);
// float y = pos.y;
// v = new Vector2(x, y);
/
本文标题为:UGUI实现ScrollView无限滚动效果
基础教程推荐
- C# 调用WebService的方法 2023-03-09
- 一个读写csv文件的C#类 2022-11-06
- C# List实现行转列的通用方案 2022-11-02
- winform把Office转成PDF文件 2023-06-14
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- ZooKeeper的安装及部署教程 2023-01-22
- C# windows语音识别与朗读实例 2023-04-27
- unity实现动态排行榜 2023-04-27
- C#类和结构详解 2023-05-30
- C#控制台实现飞行棋小游戏 2023-04-22