循环列表其实是针对列表组件的优化,如果有1000条数据普通列表会创建1000个item,这样在打开或关闭界面时会有很明显的卡顿现象。所以趁现在有空就尝试做个demo。NGUI的例子中有循环列表的例子,但是要用到项目中还得琢磨一阵子,而且这种功能自己尝试写一写是很好的事情。
先上图:
图中显示到1000条数据的位置,但是注意红框中的item个数它只有11个,所以界面打开关闭也不会有明显的卡顿,原理并不复杂,当滑动条向下滑时,第一个超过显示区域时就移动到最下面;当滑动条向上滑时,最后一个超过显示区域就移动到最上面,然后从数据集合中取出数据进行显示,如此循环即可。
1.先看看封装之后逻辑层的使用
只需要传入【列表的最大数量】和【更新item的回调事件】这两个参数。
刷新界面的代码在封装界面时就可以很自由的进行编写,嘿嘿,是不是超方便^_^?!
代码如下:
2.以下是列表的封装
初版代码如下(并不是十分完善只有垂直方向):
1. using UnityEngine;
2. using System.Collections;
3. using System.Collections.Generic;
4. using UnityEngine.UI;
5.
6. publicdelegate voidUpdateListItem(Transform item, intindex);
7. publicclassUIComUnList : MonoBehaviour {
8.
9. // UI对象绑定
10. publicTransform m_itemParent;
11. publicGameObject m_item;
12. publicScrollbar m_sb;
13.
14. // 外部参数设置
15. publicintm_itemWidth; //单元格宽
16. publicintm_itemHeight; //单元格高
17.
18. publicintm_fixedColumnCount; // 固定列数
19. publicintm_fixedColCount; // 固定行数
20.
21. // 内部私有遍历
22. privateVector2 m_allItemArea = Vector2.zero; // 当前所有内容高度
23. privateVector2 m_showArea = Vector2.zero; // 当前显示局域
24.
25. // 前后的单元格位置
26. privateVector2 m_firstItemPos = Vector2.zero;
27. privateVector2 m_lastItemPos = Vector2.zero;
28.
29. // 数据处理
30. privateintm_listMaxLength = 0;
31. privateintm_curShowStartIndex = 0;
32. privateintm_curShowEndIndex = 0;
33.
34. // 更新item内容
35. privateUpdateListItem m_updateItem;
36.
37. privatefloatm_curSbVal = 0; //记录当前值用于获取滑动方向
38. // 初始化
39. publicvoidInit(intmaxLength, UpdateListItem updateItem)
40. {
41. m_showArea = GetComponent().sizeDelta;
42. m_item.SetActive(false);
43. m_firstItemPos.y += m_itemHeight;
44. m_curSbVal = m_sb.value;
45. m_curShowEndIndex = m_fixedColCount;
46.
47. m_listMaxLength = maxLength;
48. m_updateItem = updateItem;
49. for(inti = 0; i < m_fixedColCount + 1; i++)
50. {
51. Transform item = CreateItem(i);
52. m_updateItem(item, i);
53. }
54. }
55. // 创建item
56. privateTransform CreateItem(intindex)
57. {
58. Transform item =
59. ((GameObject)GameObject.Instantiate(m_item)).transform;
60. item.gameObject.SetActive(true);
61. item.SetParent(m_itemParent);
62. item.name = index.ToString();
63. // 1.行
64. introw = index / m_fixedColumnCount;
65. // 2.列
66. intcol = index % m_fixedColumnCount;
67. item.localPosition = newVector3(col * m_itemWidth, -1* row * m_itemHeight, 0f);
68.
69. m_allItemArea.y = (row + 1) * m_itemHeight;
70. m_lastItemPos.y = -1* (int)m_allItemArea.y;
71. returnitem;
72. }
73.
74. // 滑动条值改变时调用
75. publicvoidOnDragSlider(floatval)
76. {
77. UpdateListByFloat(m_sb.value * (m_listMaxLength - m_fixedColCount));
78. }
79. // 通过一个浮点值滑动列表
80. publicvoidUpdateListByFloat(floatval)
81. {
82. UpdateListPos(val);
83. if(val > m_curSbVal)
84. {
85. if(m_curShowEndIndex >= m_listMaxLength - 1) return;
86. UpdateItemPos(true);
87. }
88. else
89. {
90. if(m_curShowStartIndex <= 0) return;
91. UpdateItemPos(false);
92. }
93. m_curSbVal = val;
94. }
95. // 更新item父节点位置
96. privatevoidUpdateListPos(floatval)
97. {
98. // 获取多出来的高度
99. floatexcess = 0f;
100. if(m_allItemArea.y > m_showArea.y)
101. {
102. excess = m_allItemArea.y - m_showArea.y;
103. }
104. m_itemParent.localPosition = newVector2(0, excess * val);
105. }
106. // 更新item位置
107. privatevoidUpdateItemPos(bool isDown)
108. {
109. if(isDown) // 下滑
110. {
111. for(inti = 0; i < m_itemParent.childCount; i++)
112. {
113. Transform item = m_itemParent.GetChild(i);
114. floatcurPos = item.localPosition.y + m_itemParent.localPosition.y;
115. if(curPos > m_itemHeight)
116. {
117. item.localPosition = newVector3(0, m_lastItemPos.y, 0);
118. m_lastItemPos.y -= m_itemHeight;
119. m_firstItemPos.y -= m_itemHeight;
120.
121. m_updateItem(item, m_curShowEndIndex + 1);
122. m_curShowStartIndex ++;
123. m_curShowEndIndex++;
124. //break;
125. }
126. }
127. }
128. else
129. {
130. for(inti = m_itemParent.childCount - 1; i >=0; i--)
131. {
132. Transform item = m_itemParent.GetChild(i);
133. floatcurPos = item.localPosition.y + m_itemParent.localPosition.y;
134. if(curPos < -1* m_showArea.y)
135. {
136. item.localPosition = newVector3(0, m_firstItemPos.y, 0);
137. m_firstItemPos.y += m_itemHeight;
138. m_lastItemPos.y += m_itemHeight;
139.
140. m_updateItem(item, m_curShowStartIndex - 1);
141. m_curShowEndIndex --;
142. m_curShowStartIndex--;
143. //break;
144. }
145. }
146. }
147. }
148. }
注:这种功能就算没有实现也不会成为游戏开发中的瓶颈,因为有很多方式可以避免数据量大引起卡顿的情况,比如使用分页,限制显示数量上限等。