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

UGUI Scrollrect滚动优化:无限循环利用

2016-06-23 04:00 639 查看

1 功能描述

在做排行榜类似界面时,item非常多,可能有几百个,一次创建这么多GameObject是非常卡的。为此,使用只创建可视区一共显示的个数,加上后置准备个数。如图所示



图中红色框是可视区,可视区一共可显示4个item,后置准备1个item.当向左滑,0号滑出可视区,4号进入可视区,把0号GameObject位置放在滑动面板最后,如同所示



同时更新滑动面板大小,和每个条目信息。这样循环下去一共创建5个gameobjec,重复利用,实现显示N个条目。如图所示



只创建了5个GameObject,可以实现N个条目的显示。

2 详细设计

2.1 初始化滑动面板

void InitValue()
{
if (ConstraintCount <= 0)
ConstraintCount = 1;
Debug.Log("maxIndex = "+ maxIndex);
if (minIndex > maxIndex) minIndex = maxIndex;
mTrans = transform;
mRTrans = transform.GetComponent<RectTransform>();
mScroll = transform.parent.GetComponent<ScrollRect>();
mHorizontal = mScroll.horizontal;

SR_size =transform.parent.GetComponent<RectTransform>().rect.size;

//四角坐标  横着数
conners[0] = new Vector3(-SR_size.x / 2f, SR_size.y / 2f,0);
conners[1] = new Vector3(SR_size.x / 2f, SR_size.y / 2f,0);
conners[2] = new Vector3(-SR_size.x / 2f, -SR_size.y / 2f,0);
conners[3] = new Vector3(SR_size.x / 2f, -SR_size.y / 2f,0);
for (int i = 0; i < 4; i++)
{
Vector3 temp = transform.parent.TransformPoint(conners[i]);//转化为世界坐标,4个顶点
conners[i].x = temp.x;
conners[i].y = temp.y;
}

mRTrans.pivot = new Vector2(0, 1);//设置panel的中心在左上角

mScroll.onValueChanged.AddListener(delegate { WrapContent(); });//添加滚动事件回调
startPos = mTrans.localPosition;
}

1.得到显示区域的4个顶点的世界坐标

2.当产生滚动时,添加滚动委托

2.2 重置滑动面板大小

void UpdateRectsize(Vector2 pos,bool isLast = true)
{
if (arrangeType == ArrangeType.Vertical)
{
mRTrans.sizeDelta = new Vector2(pos.x + cell_x/2, ConstraintCount * cell_y);
}
else
{
mRTrans.sizeDelta = new Vector2(ConstraintCount * cell_x, -pos.y + cell_y/2);
}
}

当有新的条目加入时要重新设置滑动层的大小,相当于添加ContentSizeFitter组件。

2.3滑动更新

float min = conner_local[0].x - cell_x;//显示区域
float max = conner_local[3].x + cell_x;
for (int i = 0, imax = mChild.Count; i < imax; i++)
{
Transform temp = mChild[i];
float distance = temp.localPosition.x - center.x;

if (distance <-extents)
{

Vector2 pos = temp.localPosition;
pos.x += extents * 2f;

int realIndex = getRealIndex(pos);

if (minIndex == maxIndex || (realIndex >= minIndex && realIndex < maxIndex))
{
if (i == imax -1)
UpdateRectsize(pos,true);
else
UpdateRectsize(pos);
temp.localPosition = pos;
//设置Item内容
UpdateItem(temp, i, realIndex);
}

}

if (distance > extents)
{
Vector2 pos = temp.localPosition;
pos.x -= extents * 2f;

int realIndex = getRealIndex(pos);

if (minIndex == maxIndex || (realIndex >= minIndex && realIndex < maxIndex))
{
temp.localPosition = pos;
//设置Item内容
UpdateItem(temp, i, realIndex);
}
}

1.在滑动委托中,每次遍历所有的创建的GameObject(这里是5个)

2.当水平向左滑动时,当GameObject超过可视区的最左边,把它放在可视区的最右边的预备显示位置,如图所示,0号GameObject从最前变为最后。同时增加滑动面板大小,和0号GameObject的信息显示(把0置为5)



3.当水平向右滑动时,当当GameObject超过可视区的最右边,把它放在可视区的最左边的预备显示位置,如图所示,0号GameObject从最前后为最前。0号GameObject的信息显示(把10置为5)。这样实现无限滚动。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: