无限滚动复用列表
一、Demo展示
二、前言
游戏中有非常多的下拉滚动菜单,比如成就列表,任务列表,以及背包仓库之类;如果列表内容非常丰富,会占用大量内存,这篇无限滚动复用ScrollView就是解决这种问题;还可以用来做朋友圈,聊天等;
一般情况,ScrollView中每个Item的大小是一直的,使用ContentSizeFillter组件足够解决大部分问题;
如果每个Item大小不一致,问题就复杂起来,需要做滚动位置判断,我这里做了大小适应;
三、设计思路
1.将数据部分和滚动逻辑部分分离开,数据设计成泛型类;
2.在ScrollView组件上添加ScrollView脚本,控制Item的添加和删除,分为头部和尾部;
3.在每个Item上添加ScrollItem脚本,重写更新数据方法,同时监听自身是否为头部或者尾部;
4.如果为头部或者尾部,且超界通过委托调用ScrollView脚本中的添加或删除Item方法;
四、关键基类
1.ScrollData
负责整个列表的数据管理,分为总数据和现实数据两个链表,增删查改方法;泛型类方便复用;
这里使用LinkedList方便查找并返回头尾节点;
全部代码:
public class ScrollData<T>
{
public List<T> allDatas;
public LinkedList<T> curDatas;
public ScrollData()
{
allDatas = new List<T>();
curDatas = new LinkedList<T>();
//加载数据;
}
//获取头数据
public T GetHeadData()
{
if(allDatas.Count == 0)
return default(T);
if (curDatas.Count == 0)
{
T head = allDatas[0];
curDatas.AddFirst(head);
return head;
}
T t = curDatas.First.Value;
int index = allDatas.IndexOf(t);
if (index != 0)
{
T head = allDatas[index - 1];
curDatas.AddFirst(head);
return head;
}
return default(T);
}
//移出头数据
public bool RemoveHeadData()
{
if (curDatas.Count == 0 || curDatas.Count == 1)
return false;
curDatas.RemoveFirst();
return true;
}
//获取尾部数据
public T GetEndData()
{
if (allDatas.Count == 0)
return default(T);
if (curDatas.Count == 0)
{
T end = allDatas[0];
curDatas.AddLast(end);
return end;
}
T t = curDatas.Last.Value;
int index = allDatas.IndexOf(t);
if (index != allDatas.Count - 1)
{
T end = allDatas[index + 1];
curDatas.AddLast(end);
return end;
}
return default(T);
}
//移出尾部数据
public bool RemoveEndData()
{
if (curDatas.Count == 0 || curDatas.Count == 1)
return false;
curDatas.RemoveLast();
return true;
}
//添加数据,通过数组
public void AddData(T[] t)
{
allDatas.AddRange(t);
}
//添加数据,通过链表
public void AddData(List<T> t)
{
allDatas.AddRange(t.ToArray());
}
//添加单条数据
public void AddData(T t)
{
allDatas.Insert(0,t);
curDatas.AddFirst(t