当ScrollView中Grid子级太多的时候,会导致卡顿的效果。通过重写MultiRowWrapContent的函数即可有效解决。只需要在Grid上绑定这一个脚本,填写Item的数量,以及单元格大小,滑动的时候就会自动调整Item位置,来实现完美的显示效果。
using UnityEngine;
public class MultiRowWrapContent : UIWrapContent
{
/// <summary>
/// 根据数据设置大小
/// </summary>
/// <param name="showCount">最多显示的大小</param>
/// <param name="dataCount">数据长度</param>
public void SetCurData(int showCount,int dataCount)
{
minIndex = 0;
maxIndex = dataCount - 1;
if (maxIndex < (showCount-1))
{
maxIndex = showCount-1;
}
}
public void mFWrapContent()
{
//itemSizeH = 180;
mFirstTime = true;
SortBasedOnScrollMovement();
WrapContent();
mFirstTime = false;
}
protected override void ResetChildPositions()
{
for (int i = 0, imax = mChildren.Count; i < imax; ++i)
{
Transform t = mChildren[i];
int x = i * itemSize;
int y = 0;
if (!mHorizontal)
{
x = (i % RowNum) * itemSize;
y = -(i / RowNum) * itemSizeH;
int index = int.Parse(t.gameObject.name.Substring(4,2));//item00
if (index % 4 == 0)
Debug.Log(i+t.gameObject.name+": " + y);
}
t.localPosition = new Vector3(x, y, 0);
UpdateItem(t, i);
}
}
protected override void UpdateItem(Transform item, int index)
{
if (onInitializeItem != null)
{
int yIndex = Mathf.Abs(Mathf.RoundToInt(item.localPosition.y / itemSize));
int xIndex = Mathf.Abs(Mathf.RoundToInt(item.localPosition.x / itemSize));
int realIndex = RowNum * yIndex + xIndex;
onInitializeItem(item.gameObject, index, realIndex);
}
}
public override void SortBasedOnScrollMovement()
{
if (!CacheScrollView()) return;
// Cache all children and place them in order
mChildren.Clear();
for (int i = 0; i < mTrans.childCount; ++i)
{
Transform t = mTrans.GetChild(i);
if (hideInactive && !t.gameObject.activeInHierarchy) continue;
mChildren.Add(t);
}
ResetChildPositions();
}
public override void WrapContent()
{
float extents = itemSize * (mChildren.Count / RowNum) * 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 == maxIndex || (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 == 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
{
extents = itemSizeH * (mChildren.Count / RowNum) * 0.5f;
ext2 = extents * 2f;
float min = corners[0].y - itemSizeH;
float max = corners[2].y + itemSizeH;
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 yIndex = -Mathf.RoundToInt(pos.y / itemSizeH);
int xIndex = -Mathf.RoundToInt(pos.x / itemSize);
int realIndex = RowNum * yIndex;
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);
// int yIndex = Mathf.Abs(Mathf.RoundToInt(pos.y / itemSize));
// int xIndex = Mathf.Abs(Mathf.RoundToInt(pos.x / itemSize));
int yIndex = -Mathf.RoundToInt(pos.y / itemSizeH);
int xIndex = -Mathf.RoundToInt(pos.x / itemSize);
int realIndex = RowNum * yIndex;
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;
mScroll.InvalidateBounds();
}
}