UGUI(十)_无限循环列表

来源:互联网 发布:品高软件 编辑:程序博客网 时间:2024/04/27 16:55

UGUI(十)_无限循环列表 

循环列表其实是针对列表组件的优化,如果有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 void UpdateListItem(Transform item, int 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(int maxLength, 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 (int i = 0; i < m_fixedColCount + 1; i++)          {              Transform item = CreateItem(i);              m_updateItem(item, i);          }      }      // 创建item      private Transform CreateItem(int 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 * m_itemWidth, -1 * row * m_itemHeight, 0f);            m_allItemArea.y = (row + 1) * m_itemHeight;          m_lastItemPos.y = -1 * (int)m_allItemArea.y;          return item;    }        // 滑动条值改变时调用      public void OnDragSlider(float val)      {          UpdateListByFloat(m_sb.value * (m_listMaxLength - m_fixedColCount));      }      // 通过一个浮点值滑动列表      public void UpdateListByFloat(float val)      {          UpdateListPos(val);          if (val > m_curSbVal)          {              if (m_curShowEndIndex >= m_listMaxLength - 1) return;              UpdateItemPos(true);          }          else          {              if (m_curShowStartIndex <= 0) return;              UpdateItemPos(false);          }          m_curSbVal = val;      }      // 更新item父节点位置      private void UpdateListPos(float val)      {          // 获取多出来的高度          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 (int i = 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 (int i = m_itemParent.childCount - 1; 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;                  }              }          }      }  }


0 0