您的位置:首页 > 产品设计 > UI/UE

NGUI ScrollView实现循环优化

2016-01-04 20:52 639 查看
List<DataUnit> dataList;

当dataList的数据很多时,如果直接把所有的item挂在UIGrid下面,效率显然是十分低下的。这时用UIWrapContent就可以实现列表的循环复用(通过循环几个item实例表现大量的数据)

在NGUI中高效优化UIScrollView之UIWrapContent的简介以及使用

UIWrapContent的大致用法:

a)UIWrapContent.onInitializeItem是列表循环复用时重设表项数据的委托:

class xxx: MonoBehaviour
{
public UIWrapContent _wrapScript;
void Awake()
{
//绑定方法
_wrapScript.onInitializeItem = OnUpdateItem;
}
void OnUpdateItem(GameObject go, int index, int realIndex)
{
tb.SetNumber(realIndex.ToString());
}
}


b)当列表为横向时 minIndex=0,maxIndex= dataList.Count-1;当列表为纵向时 minIndex = -dataList.Count+1,maxIndex =0;

c)用代码addChild item后需要手动调用一次SortBasedOnScrollMovement()刷新界面

d)当dataList.Count==1时 minIndex==maxIndex==0 。按照UIWrapContent的逻辑,这种情况实现的是无限循环列表,不符合当前的需求,所以要对UIWrapContent.WrapContent进行改写:

/// <summary>
/// Wrap all content, repositioning all children as needed.
/// </summary>

public void WrapContent ()
{
float extents = itemSize * mChildren.Count * 0.5f;
Vector3[] corners = mPanel.worldCorners;

for (int i = 0; i < 4; ++i)
{
Vector3 v = corners[i];
v = mTrans.InverseTransformPoint(v);
corners[i] = v;
}

Vector3 center = Vector3.Lerp(corners[0], corners[2], 0.5f);
bool allWithinRange = true;
float ext2 = extents * 2f;

if (mHorizontal)
{
float min = corners[0].x - itemSize;
float max = corners[2].x + itemSize;

for (int i = 0, imax = mChildren.Count; i < imax; ++i)
{
Transform t = mChildren[i];
float distance = t.localPosition.x - center.x;

if (distance < -extents)
{
Vector3 pos = t.localPosition;
pos.x += ext2;
distance = pos.x - center.x;
int realIndex = Mathf.RoundToInt(pos.x / itemSize);
if ((minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
UpdateItem(t, i);
}
else allWithinRange = false;
}
else if (distance > extents)
{
Vector3 pos = t.localPosition;
pos.x -= ext2;
distance = pos.x - center.x;
int realIndex = Mathf.RoundToInt(pos.x / itemSize);
if ((minIndex <= realIndex && realIndex <= maxIndex))
//if (minIndex == maxIndex || (minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
UpdateItem(t, i);
}
else allWithinRange = false;
}
else if (mFirstTime) UpdateItem(t, i);

if (cullContent)
{
distance += mPanel.clipOffset.x - mTrans.localPosition.x;
if (!UICamera.IsPressed(t.gameObject))
NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);
}
}
}
else
{
float min = corners[0].y - itemSize;
float max = corners[2].y + itemSize;

for (int i = 0, imax = mChildren.Count; i < imax; ++i)
{
Transform t = mChildren[i];
float distance = t.localPosition.y - center.y;

if (distance < -extents)
{
Vector3 pos = t.localPosition;
pos.y += ext2;
distance = pos.y - center.y;
int realIndex = Mathf.RoundToInt(pos.y / itemSize);
if ((minIndex <= realIndex && realIndex <= maxIndex))
//    if (minIndex == maxIndex || (minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
UpdateItem(t, i);
}
else allWithinRange = false;
}
else if (distance > extents)
{
Vector3 pos = t.localPosition;
pos.y -= ext2;
distance = pos.y - center.y;
int realIndex = Mathf.RoundToInt(pos.y / itemSize);
if ((minIndex <= realIndex && realIndex <= maxIndex))

//    if (minIndex == maxIndex || (minIndex <= realIndex && realIndex <= maxIndex))
{
t.localPosition = pos;
UpdateItem(t, i);
}
else allWithinRange = false;
}
else if (mFirstTime) UpdateItem(t, i);

if (cullContent)
{
distance += mPanel.clipOffset.y - mTrans.localPosition.y;
if (!UICamera.IsPressed(t.gameObject))
NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);
}
}
}
mScroll.restrictWithinPanel = !allWithinRange;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: