测试:

数据 & Item  的 Ctrl :

 using UnityEngine;

 public class ScrollViewItemData
{
public int index;
public string name;
public ScrollViewItemData(int index, string name)
{
this.index = index;
this.name = name;
}
} public class ScrollViewItem : MonoBehaviour
{
UISprite sprBG;
UILabel label;
public ScrollViewItemData data; void Awake()
{
sprBG = GetComponent<UISprite>();
label = transform.Find("Label").GetComponent<UILabel>();
} public Vector3 BgSize
{
get
{
if (null != sprBG)
return sprBG.localSize;
return Vector3.zero;
} } public int BgHeigth
{
get
{
if (null != sprBG)
return sprBG.height;
return ;
}
} public void SetData(ScrollViewItemData data, int index)
{
this.data = data;
label.text = data.name;
sprBG.Update();
//sprBG.ForceUpdate();
this.gameObject.name = index.ToString();
}
}

Item 大小一致的实现代码:

using System.Collections.Generic;
using UnityEngine; public class ScrollViewManager : MonoBehaviour
{
[SerializeField]
GameObject itemPrefab; List<ScrollViewItem> itemList = new List<ScrollViewItem>();
List<ScrollViewItemData> itemDataList = new List<ScrollViewItemData>(); UIScrollView sv;
UIGrid grid; //记录scrollviet上一次的位置,用于判断scrollview的移动方向
float svLastPos = ; //最大y坐标
float maxHeight = ; //最小y坐标
float minHeight = ; // Use this for initialization
void Start()
{
//初始化测试数据 for (int i = ; i < ; i++)
{
itemDataList.Add(new ScrollViewItemData(i, "第 " + (i + ) + " 个元素"));
} sv = transform.GetComponent<UIScrollView>();
grid = transform.Find("Grid").GetComponent<UIGrid>(); Vector2 viewsize = transform.GetComponent<UIPanel>().GetViewSize();
int count = (int)(viewsize.y / grid.cellHeight + );
Debug.Log(count);
for (int i = ; i < count; i++)
{
if (itemDataList.Count <= i)
break; GameObject obj = NGUITools.AddChild(grid.gameObject, itemPrefab); ScrollViewItem item = obj.GetComponent<ScrollViewItem>();
itemList.Add(item); item.SetData(itemDataList[i], i);
}
grid.repositionNow = true;
grid.Reposition(); svLastPos = grid.transform.localPosition.y; maxHeight = viewsize.y / + grid.cellHeight / ; minHeight = -maxHeight; itemPrefab.SetActive(false); } // Update is called once per frame
void Update()
{
float moveDis = sv.transform.localPosition.y - svLastPos;
if (Mathf.Abs(moveDis) > 0.05)
{
bool isup = moveDis > ;
if (isup)
{
while (itemList[].transform.localPosition.y + sv.transform.localPosition.y > maxHeight &&
itemList[itemList.Count - ].data.index < itemDataList.Count - )
{
ScrollViewItem item = itemList[];
item.SetData(itemDataList[itemList[itemList.Count - ].data.index + ], item.data.index); itemList.Add(item);
itemList.RemoveAt(); item.transform.localPosition = itemList[itemList.Count - ].transform.localPosition - new Vector3(, grid.cellHeight, );
}
}
else
{
while (itemList[itemList.Count - ].transform.localPosition.y + sv.transform.localPosition.y < minHeight &&
itemList[].data.index > )
{
ScrollViewItem item = itemList[itemList.Count - ];
item.SetData(itemDataList[itemList[].data.index - ], item.data.index); itemList.Insert(, item);
itemList.RemoveAt(itemList.Count - ); item.transform.localPosition = itemList[].transform.localPosition + new Vector3(, grid.cellHeight, );
}
} svLastPos = sv.transform.localPosition.y;
}
}
}

Item 大小不一致的代码实现:

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine; public class GUIScrollViewManager : MonoBehaviour
{
[SerializeField]
GameObject itemPrefab; List<ScrollViewItem> itemList = new List<ScrollViewItem>();
List<ScrollViewItemData> itemDataList = new List<ScrollViewItemData>();
List<String> strList = new List<string>(); UIScrollView sv;
UITable table; //记录scrollviet上一次的位置,用于判断scrollview的移动方向
float svLastPos = ; //最大y坐标
float maxHeight = 288.0f; //最小y坐标
float minHeight = -288.0f; const string tmpStr = "初始化测试数据";
const int Count = ; // Use this for initialization
void Start()
{
//初始化测试数据
System.Random random = new System.Random();
StringBuilder sb = new StringBuilder(); int sbCounter = ;
for (int i = ; i < Count; i++)
{
int tmpCount = random.Next(, );
sbCounter = ;
while (sbCounter < tmpCount)
{
++sbCounter;
sb.Append(tmpStr);
}
itemDataList.Add(new ScrollViewItemData(i, "第 " + (i + ) + " 个元素" + sb.ToString()));
sb.Remove(, sb.Length); } sv = transform.GetComponent<UIScrollView>();
table = transform.Find("Table").GetComponent<UITable>(); int count = ;
for (int i = ; i < count; i++)
{
if (itemDataList.Count <= i)
break; GameObject obj = NGUITools.AddChild(table.gameObject, itemPrefab);
ScrollViewItem item = obj.GetComponent<ScrollViewItem>();
itemList.Add(item); item.SetData(itemDataList[i], i);
} table.Reposition(); itemPrefab.SetActive(false);
} void Update()
{
float moveDis = sv.transform.localPosition.y - svLastPos; if (Mathf.Abs(moveDis) > 0.05)
{
bool isup = moveDis > ;
if (isup)
{
float height = NGUIMath.CalculateRelativeWidgetBounds(itemList[].transform).size.y;
while (itemList[].transform.localPosition.y + sv.transform.localPosition.y - height > maxHeight &&
itemList[itemList.Count - ].data.index < itemDataList.Count - )
{
ScrollViewItem item = itemList[];
item.SetData(itemDataList[itemList[itemList.Count - ].data.index + ], item.data.index); itemList.Add(item);
itemList.RemoveAt(); float _height = NGUIMath.CalculateRelativeWidgetBounds(itemList[itemList.Count - ].transform).size.y;
item.transform.localPosition = itemList[itemList.Count - ].transform.localPosition - new Vector3(, _height + , );
}
}
else
{
while (itemList[itemList.Count - ].transform.localPosition.y + sv.transform.localPosition.y < minHeight &&
itemList[].data.index > )
{
ScrollViewItem item = itemList[itemList.Count - ];
item.SetData(itemDataList[itemList[].data.index - ], item.data.index); itemList.Insert(, item);
itemList.RemoveAt(itemList.Count - ); float _height = NGUIMath.CalculateRelativeWidgetBounds(item.transform).size.y;
item.transform.localPosition = itemList[].transform.localPosition + new Vector3(, _height + , );
} } svLastPos = sv.transform.localPosition.y;
}
}
}

以上两种情况下 Prefab 的结构如下:

效果:

  

具体到项目中的实现代码(只记录了大致逻辑,具体细节无记录):

 using ClientData;
using Modules.UI;
using System;
using System.Collections.Generic;
using UnityEngine; /// <summary>
/// Item 大小可变的动态循环列表实现(只支持竖向,暂且未实现对横向的支持)
/// 该脚本需要挂在 UIScrollView 所在的 gameObject 上
/// </summary>
public class DynamicFlexibleSizeScrollView : MonoBehaviour
{
//定义的一些 delegate 为了,实现组件的通用化,把逻辑的实现下放到具体的实例中
public delegate void OnInitItem(DFSItemCtrl item, DFSItemData data);
public delegate void OnHideAllItem(List<DFSItemCtrl> itemList);
public delegate DFSItemCtrl OnGetItemCtrl();
public delegate void OnRecycleAllChatInfoCell(List<DFSItemCtrl> list); [SerializeField]
Vector2 originalPanelClipOffset = new Vector2(, );
[SerializeField]
Vector3 originalPanelPosition = new Vector3(, , );
[SerializeField]
Vector3 originalTablePosition = new Vector3(, , );
[SerializeField]
float maxHeight; //最大y坐标
[SerializeField]
float minHeight; //最小y坐标
[SerializeField]
int itemCount = ; //创建多少数量的 item 来做循环滚动
[SerializeField]
float offset = 6.0f; //item 中间空出的距离 float svLastPos = ; //记录scrollviet上一次的位置,用于判断scrollview的移动方向
List<DFSItemCtrl> itemList = new List<DFSItemCtrl>();
List<DFSItemData> itemDataList = new List<DFSItemData>();
UIScrollView sv;
UIPanel currUIPanel;
UITable table; //只是在初始化的时候会用到,在滑动的时候,不会再次操作该组件 void InitNGUIComponent()
{
if (null == sv)
sv = GetComponent<UIScrollView>(); if (null != sv && null == currUIPanel)
currUIPanel = sv.panel; if (null == table)
table = GetComponentInChildren<UITable>();
} public float MaxHeight
{
set { maxHeight = value; }
} public float MinHeight
{
set { minHeight = value; }
} public OnInitItem onInitItem; //刷新 item
public OnHideAllItem onHideAllItem; //隐藏所有 item public OnGetItemCtrl getItemCtrl;
public OnRecycleAllChatInfoCell recycleAllChatInfoCell; bool CheckContainData(DFSItemData data)
{
if (null != data)
{
for (int i = , iMax = itemDataList.Count - ; i <= iMax; ++i)
{
if (itemDataList[i].Index == data.Index)
return true;
}
} return false;
} void AddData(DFSItemData data)
{
if (!CheckContainData(data))
{
itemDataList.Add(data);
}
} DFSItemCtrl tmpCtrl = null;
public void ShowSingleItem(DFSItemData data)
{
if (null == data) return; InitNGUIComponent(); AddData(data); if (itemList.Count < itemCount)
{
AddItem(data); if (null != table)
table.Reposition(); if (null != sv)
sv.ResetPosition();
}
else
{
AutoDragUIPanelByData(data);
}
} void AutoDragUIPanelByData(DFSItemData data)
{
if (null != data)
{
if (null != getItemCtrl)
{
//从池中拿出一个 item 计算 panel 需要移动的位置
if (null == tmpCtrl)
tmpCtrl = getItemCtrl(); if (null != tmpCtrl && null != onInitItem)
{
onInitItem(tmpCtrl, data);
float height = NGUIMath.CalculateRelativeWidgetBounds(tmpCtrl.transform).size.y;
Vector2 vec2 = new Vector2(, height + offset);
SetPanelClipOff(vec2);
tmpCtrl.cachedGameObject.SetActive(false);
}
}
}
} void SetPanelClipOff(Vector2 vec2)
{
Vector2 tmpOff = currUIPanel.clipOffset;
tmpOff -= vec2;
currUIPanel.clipOffset = tmpOff; Vector3 tmpPos = currUIPanel.cachedTransform.localPosition;
tmpPos = new Vector3(tmpPos.x, -tmpOff.y, );
currUIPanel.cachedTransform.localPosition = tmpPos;
} public void ShowAllItems(List<DFSItemData> dataList)
{
if (null == dataList) return; svLastPos = ;
InitNGUIComponent(); if (null != sv)
{
currUIPanel.clipOffset = originalPanelClipOffset;
sv.transform.localPosition = originalPanelPosition;
}
if (null != table)
table.transform.localPosition = originalTablePosition; //数据保存
for (int i = , iMax = dataList.Count; i < iMax; ++i)
AddData(dataList[i]); //如果数据数量大于了创建的item数量,自动滑动panel
if (itemDataList.Count > itemCount)
{
int i = itemDataList.Count - itemCount,
iMax = itemDataList.Count;
for (; i < iMax; ++i)
{
AddItem(itemDataList[i]);
}
}
else
{
for (int i = ; i < itemCount; ++i)
{
if (itemDataList.Count <= i) break;
AddItem(itemDataList[i]);
} } ResetPanelStatus();
} void ResetPanelStatus()
{
if (null != table)
table.Reposition();
if (null != sv)
sv.ResetPosition();
} public void RecycleAllChatInfoCell()
{
if (null != recycleAllChatInfoCell)
recycleAllChatInfoCell(itemList);
itemDataList.Clear();
} void AddItem(DFSItemData data)
{
DFSItemCtrl item = null;
if (null != getItemCtrl)
item = getItemCtrl(); if (null != data && null != item && null != onInitItem)
{
this.itemList.Add(item);
item.cachedTransform.parent = table.transform;
onInitItem(item, data);
}
} void Update()
{
if (null == onInitItem || null == itemDataList || itemList.Count <= ) return; float moveDis = sv.transform.localPosition.y - svLastPos; if (Mathf.Abs(moveDis) > 0.05)
{
bool isup = moveDis > ;
if (isup)
{
float height = NGUIMath.CalculateRelativeWidgetBounds(itemList[].transform).size.y;
while (itemList[].transform.localPosition.y + sv.transform.localPosition.y - height > maxHeight &&
itemList[itemList.Count - ].Data.Index < itemDataList.Count - )
{
DFSItemCtrl item = itemList[];
DFSItemData data = itemDataList[itemList[itemList.Count - ].Data.Index + ];
onInitItem(item, data); itemList.Add(item);
itemList.RemoveAt(); float _height = NGUIMath.CalculateRelativeWidgetBounds(itemList[itemList.Count - ].transform).size.y;
item.transform.localPosition = itemList[itemList.Count - ].transform.localPosition - new Vector3(, _height + offset, );
}
}
else
{
while (itemList[itemList.Count - ].transform.localPosition.y + sv.transform.localPosition.y < minHeight &&
itemList[].Data.Index > )
{
DFSItemCtrl item = itemList[itemList.Count - ];
DFSItemData data = itemDataList[itemList[].Data.Index - ];
onInitItem(item, data); itemList.Insert(, item);
itemList.RemoveAt(itemList.Count - ); float _height = NGUIMath.CalculateRelativeWidgetBounds(item.transform).size.y;
item.transform.localPosition = itemList[].transform.localPosition + new Vector3(, _height + offset, );
}
} svLastPos = sv.transform.localPosition.y;
}
}
} /// <summary>
/// 列表中显示的 Item ,应用到项目的时候,实际的 Item 可以继承自该类
/// </summary>
public class DFSItemCtrl : MonoBehaviour
{
protected DFSItemData data; public DFSItemData Data
{
get { return data; }
} GameObject obj = null;
public GameObject cachedGameObject
{
get
{
if (null == obj)
obj = gameObject;
return obj;
}
} Transform tran = null;
public Transform cachedTransform
{
get
{
if (null == tran)
tran = transform;
return tran;
}
} public void ForceUpdateItemSize()
{ } public virtual void SetData(DFSItemData data,params UnityEngine.Object[] list)
{
if (null != data)
{
this.data = data;
ChatInfo info = data as ChatInfo;
this.cachedGameObject.name = info.Index.ToString();
} //强制刷新一下 Item 的大小
ForceUpdateItemSize();
}
} /// <summary>
/// ItemData ,应用到项目的时候,实际的数据可以继承自该类
/// </summary>
public class DFSItemData
{
int index = -; public virtual int Index
{
get { return index; }
set { index = value; }
}
}

效果:

NGUI实现的一套不同大小 Item 的循环滚动代码的更多相关文章

  1. UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(二)

    上篇UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(一) 讲到该控件的需要和设计过程. 这篇讲讲开发过程中一些重要问题解决. 1.支持 ...

  2. 套接字TCP控制台服务器程序代码示范

    套接字TCP控制台服务器程序代码示范  https://blog.csdn.net/txwtech/article/details/90344081

  3. UWP VirtualizedVariableSizedGridView 支持可虚拟化可变大小Item的View(一)

    Boss的需要时这样的,Item是可变大小的,同时根据不同的Window size,来确定Item的结构和大小Window 小的时候是 大的时候是这样的: 当然这size变化的过程中也允许其他结构,我 ...

  4. 【一套C语言控制台的输出框代码】

    效果演示 可以生成一个输出框 首先 要创建输出框,设置输出框风格,可以设置的元素包括: 左上角符号,右上角符号,左下角符号,右下角符号,以及上下左右边界线符号,理论上,只要你电脑能显示的符号,都可以支 ...

  5. 元素大小-偏移量(offset)客户区大小(client)滚动大小(scroll)

    一.偏移量---offset 1.定位父级 在理解偏移大小之前,首先要理解offsetParent.人们并没有把offsetParent翻译为偏移父级,而是翻译成定位父级,很大原因是offsetPar ...

  6. item上下自动循环滚动显示

    //li 上下滚动 (function($){ $.fn.extend({ Scroll:function(opt,callback){ //参数初始化 if(!opt) var opt={}; va ...

  7. 使用 Spring Boot 搭建一套增删改查(无多余代码)

    前言 这是我学习 Spring Boot 的第三篇文章,终于可以见到效果了.错过的同学可以看看之前的文章 我们为什么要学习 Spring Boot Spring Boot 入门详细分析 在入门的基础上 ...

  8. NGUI 中,长技能图标显示技能Tips的核心代码

    需要将技能图标对应的位置Pos赋给Tips即可.下面是计算 Pos 的核心代码: using UnityEngine; public class LgsTest : MonoBehaviour { [ ...

  9. Android中当item数量超过一定大小RecyclerView高度固定

    Android中当item数量超过一定大小时,将RecyclerView高度固定 方法1 直接通过LayoutParams来设定相应高度 ViewGroup.LayoutParams lp = rv. ...

随机推荐

  1. TCP编程:系统出现 TIME_WAIT 原因及解决办法

    解决办法 打开 sysctl.conf 文件,修改以下几个参数: net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_ti ...

  2. mycat下mysql jdbc connector使用高版本报PacketTooBigException异常

    如下所示: 5.1.30切换为mysql-connector 5.1.46/40,报错,可参考https://blog.csdn.net/n447194252/article/details/7530 ...

  3. intel webrtc 部署

    org link conference server Configure the MCU server 1. set the maximum numbers of open files, runnin ...

  4. bzoj 4289 Tax - 最短路

    题目传送门 这是一条通往vjudge的神秘通道 这是一条通往bzoj的神秘通道 题目大意 如果一条路径走过的边依次为$e_{1}, e_{2}, \cdots , e_{k}$,那么它的长度为$e_{ ...

  5. Python3基础 dict clear 清空一个字典

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  6. Windows使用(类)Unix环境那些事

    之前的博文中有不少涉及到win下使用unix环境的一些东西,但都是为了做别的事情,还是写一个专门讲这个主题的文章吧. 主角:Cygwin.mingw-W64.MSYS2. 注:mingw已经停止更新很 ...

  7. 配置vim

    VundleVuldle是一个全自动的插件管理器,让我们通过维护插件列表的方式管理插件.它为安装.更新.删除插件提供了方便的命令.在安装Git的情况下(本文不赘述Git的安装),输入命令: git c ...

  8. 马虎的算式|2013年蓝桥杯B组题解析第二题-fishers

    小明是个急性子,上小学的时候经常把老师写在黑板上的题目抄错了. 有一次,老师出的题目是:36 x 495 = ? 他却给抄成了:396 x 45 = ? 但结果却很戏剧性,他的答案竟然是对的!! 假设 ...

  9. Directional RNA-seq data -which parameters to choose?

    Directional RNA-seq data -which parameters to choose? REF: https://chipster.csc.fi/manual/library-ty ...

  10. vs 附加进程 iis进程显示