循环列表其实是针对列表组件的优化,如果有1000条数据普通列表会创建1000个item,这样在打开或关闭界面时会有很明显的卡顿现象。所以趁现在有空就尝试做个demo。NGUI的例子中有循环列表的例子,但是要用到项目中还得琢磨一阵子,而且这种功能自己尝试写一写是很好的事情。

先上图:

unity josn 遍历 unity无限循环列表_滑动条

图中显示到1000条数据的位置,但是注意红框中的item个数它只有11个,所以界面打开关闭也不会有明显的卡顿,原理并不复杂,当滑动条向下滑时,第一个超过显示区域时就移动到最下面;当滑动条向上滑时,最后一个超过显示区域就移动到最上面,然后从数据集合中取出数据进行显示,如此循环即可。

1.先看看封装之后逻辑层的使用

只需要传入【列表的最大数量】和【更新item的回调事件】这两个参数。

刷新界面的代码在封装界面时就可以很自由的进行编写,嘿嘿,是不是超方便^_^?!

代码如下:

unity josn 遍历 unity无限循环列表_封装_02

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. }

注:这种功能就算没有实现也不会成为游戏开发中的瓶颈,因为有很多方式可以避免数据量大引起卡顿的情况,比如使用分页,限制显示数量上限等。