循环列表其实是针对列表组件的优化,如果有1000条数据普通列表会创建1000个item,这样在打开或关闭界面时会有很明显的卡顿现象。所以趁现在有空就尝试做个demo。NGUI的例子中有循环列表的例子,但是要用到项目中还得琢磨一阵子,而且这种功能自己尝试写一写是很好的事情。
先上图:
图中显示到1000条数据的位置,但是注意红框中的item个数它只有11个,所以界面打开关闭也不会有明显的卡顿,原理并不复杂,当滑动条向下滑时,第一个超过显示区域时就移动到最下面;当滑动条向上滑时,最后一个超过显示区域就移动到最上面,然后从数据集合中取出数据进行显示,如此循环即可。
1.先看看封装之后逻辑层的使用
只需要传入【列表的最大数量】和【更新item的回调事件】这两个参数。
刷新界面的代码在封装界面时就可以很*的进行编写,嘿嘿,是不是超方便^_^?!
代码如下:
2.以下是列表的封装
初版代码如下(并不是十分完善只有垂直方向):
- using
UnityEngine; - using
System.Collections; - using
System.Collections.Generic; - using
UnityEngine.UI; -
- public
delegate voidUpdateListItem(Transform intitem, index); - public
class UIComUnList : MonoBehaviour { -
-
// UI对象绑定 -
public Transform m_itemParent; -
public GameObject m_item; -
public Scrollbar m_sb; -
-
// 外部参数设置 -
public int m_itemWidth; //单元格宽 -
public int m_itemHeight; //单元格高 -
-
public int m_fixedColumnCount; //固定列数 -
public int m_fixedColCount; //固定行数 -
-
// 内部私有遍历 -
private Vector2 //m_allItemArea = Vector2.zero; 当前所有内容高度 -
private Vector2 //m_showArea = Vector2.zero; 当前显示局域 -
-
// 前后的单元格位置 -
private Vector2 m_firstItemPos = Vector2.zero; -
private Vector2 m_lastItemPos = Vector2.zero; -
-
// 数据处理 -
private int m_listMaxLength 0;= -
private int m_curShowStartIndex 0;= -
private int m_curShowEndIndex 0;= -
-
// 更新item内容 -
private UpdateListItem m_updateItem; -
-
private float m_curSbVal 0;= //记录当前值用于获取滑动方向 -
// 初始化 -
public void Init( intmaxLength, UpdateListItem updateItem) -
{ -
m_showArea = GetComponent().sizeDelta; -
m_item.SetActive(false); -
m_firstItemPos.y += m_itemHeight; -
m_curSbVal = m_sb.value; -
m_curShowEndIndex = m_fixedColCount; -
-
m_listMaxLength = maxLength; -
m_updateItem = updateItem; -
for ( inti 0;= i 1;< m_fixedColCount + i++) -
{ -
Transform item = CreateItem(i); -
m_updateItem(item, i); -
} -
} -
// 创建item -
private Transform intCreateItem( index) -
{ -
Transform item = -
((GameObject)GameObject.Instantiate(m_item)).transform; -
item.gameObject.SetActive(true); -
item.SetParent(m_itemParent); -
item.name = index.ToString(); -
// 1.行 -
int row = index / m_fixedColumnCount; -
// 2.列 -
int col = index % m_fixedColumnCount; -
item.localPosition = new Vector3(col 1* m_itemWidth, - * row * m_itemHeight, 0f); -
-
m_allItemArea.y = (row + 1) * m_itemHeight; -
m_lastItemPos.y = -1 * int)m_allItemArea.y;( -
return item; -
} -
-
// 滑动条值改变时调用 -
public void OnDragSlider( floatval) -
{ -
UpdateListByFloat(m_sb.value * (m_listMaxLength - m_fixedColCount)); -
} -
// 通过一个浮点值滑动列表 -
public void UpdateListByFloat( floatval) -
{ -
UpdateListPos(val); -
if (val > m_curSbVal) -
{ -
if (m_curShowEndIndex 1)>= m_listMaxLength - return; -
UpdateItemPos(true); -
} -
else -
{ -
if (m_curShowStartIndex 0)<= return; -
UpdateItemPos(false); -
} -
m_curSbVal = val; -
} -
// 更新item父节点位置 -
private void UpdateListPos( floatval) -
{ -
// 获取多出来的高度 -
float excess = 0f; -
if (m_allItemArea.y > m_showArea.y) -
{ -
excess = m_allItemArea.y - m_showArea.y; -
} -
m_itemParent.localPosition = new Vector2( 0,excess * val); -
} -
// 更新item位置 -
private void UpdateItemPos(bool isDown) -
{ -
if (isDown) //下滑 -
{ -
for ( inti 0;= i < m_itemParent.childCount; i++) -
{ -
Transform item = m_itemParent.GetChild(i); -
float curPos = item.localPosition.y + m_itemParent.localPosition.y; -
if (curPos > m_itemHeight) -
{ -
item.localPosition = new Vector3( 0,m_lastItemPos.y, 0); -
m_lastItemPos.y -= m_itemHeight; -
m_firstItemPos.y -= m_itemHeight; -
-
m_updateItem(item, m_curShowEndIndex + 1); -
m_curShowStartIndex ++; -
m_curShowEndIndex++; -
//break; -
} -
} -
} -
else -
{ -
for ( inti 1;= m_itemParent.childCount - i 0>= ; i--) -
{ -
Transform item = m_itemParent.GetChild(i); -
float curPos = item.localPosition.y + m_itemParent.localPosition.y; -
if (curPos 1< - * m_showArea.y) -
{ -
item.localPosition = new Vector3( 0,m_firstItemPos.y, 0); -
m_firstItemPos.y += m_itemHeight; -
m_lastItemPos.y += m_itemHeight; -
-
m_updateItem(item, m_curShowStartIndex - 1); -
m_curShowEndIndex --; -
m_curShowStartIndex--; -
//break; -
} -
} -
} -
} - }
注:这种功能就算没有实现也不会成为游戏开发中的瓶颈,因为有很多方式可以避免数据量大引起卡顿的情况,比如使用分页,限制显示数量上限等。