UnityUI组件ScrollRect实现⽆限滚动条
在游戏开发中经常遇到滚动显⽰的数据,特别是商店商品排⾏榜 .......等数据很多,每⼀条数据去加载⼀个UI来显⽰显然对内存浪费很⼤,这种情况处理⼀般就是⽤⼏个显⽰条可滚动循环显⽰⽆限数据条。本篇介绍实现过程和⼤体思路以及可重⽤的滑动脚本InfinityGridLayoutGroup和MarketLayoutGroup数据管理刷新脚本。MarketElement类要看具体项⽬中具体数据结构来设计;仅供参考。
⼀ .总体流程
建⼀个循环滑动脚本 InfinityGridLayoutGroup类并且有删除刷新功能;
⼀个数据管理刷新脚本如:MarketLayoutGroup(商店市场数据刷新管理器),继承InfinityGridLayoutGroup类并且在滑动的时候给每条数据对象赋值显⽰;
⼀个单数据对象MarketElement;
⼀个UI ⽤于显⽰滑动;
1 .InfinityGridLayoutGroup类:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
[RequireComponent(typeof(GridLayoutGroup))]
[RequireComponent(typeof(ContentSizeFitter))]
public class InfinityGridLayoutGroup : MonoBehaviour
{
public int minAmount = 0;//实现⽆限滚动,需要的最少的child数量。屏幕上能看到的+⼀⾏看不到的,⽐如我在屏幕上能看到 2 ⾏,每⼀⾏ 2 个。则这个值为 2⾏*2个 + 1 ⾏* 2个 = 6个。
public bool changePanel = false;//切换⾯板
public bool up = false;
RectTransform rectTransform;
GridLayoutGroup gridLayoutGroup;
ContentSizeFitter contentSizeFitter;
ScrollRect scrollRect;
List<RectTransform> children = new List<RectTransform>();
Vector2 startPosition;
public int amount = 0;
public delegate void UpdateChildrenCallbackDelegate(int index, Transform trans);
public UpdateChildrenCallbackDelegate updateChildrenCallback = null;
public int realIndex = -1;
int realIndexUp = -1; //从下往上;
#region // 改动
Vector2 gridLayoutSizeLast;
Vector2 gridLayoutPosLast;
Vector2 currentPos;
#endregion
public bool hasInit = false;
Vector2 gridLayoutSize;
Vector2 gridLayoutPos;
Dictionary<Transform, Vector2> childsAnchoredPosition = new Dictionary<Transform, Vector2>();
Dictionary<Transform, int> childsSiblingIndex = new Dictionary<Transform, int>();
// Use this for initialization
void Start()
{
StartCoroutine(InitChildren());
}
IEnumerator InitChildren()
{
yield return 0;
// Debug.Log("hasInit" + hasInit);
minAmount = transform.childCount;
if (!hasInit)
{
/
/childsAnchoredPosition.Clear();
//获取Grid的宽度;
rectTransform = GetComponent<RectTransform>();
gridLayoutGroup = GetComponent<GridLayoutGroup>();
contentSizeFitter = GetComponent<ContentSizeFitter>();
gridLayoutSizeLast = rectTransform.sizeDelta;
gridLayoutPos = rectTransform.anchoredPosition;
gridLayoutSize = rectTransform.sizeDelta;
// Debug.Log("<Color=Red>children</Color>---" + children.Count + "realIndex---" + realIndex);
/
/注册ScrollRect滚动回调;
scrollRect = transform.parent.GetComponent<ScrollRect>();
//获取所有child anchoredPosition 以及 SiblingIndex;
for (int index = 0; index < transform.childCount; index++)
{
Transform child = transform.GetChild(index);
RectTransform childRectTrans = child.GetComponent<RectTransform>();
childsAnchoredPosition.Add(child, childRectTrans.anchoredPosition);
childsSiblingIndex.Add(child, child.GetSiblingIndex());
}
/
/Debug.Log("<Color=Blue>children</Color>---" + children.Count + "realIndex---" + realIndex);
}
else
{
//Debug.Log("gridLayoutPosLast--" + gridLayoutSizeLast.y);
rectTransform.anchoredPosition = new Vector2(gridLayoutPos.x, );
// Debug.Log("current--" + currentPos.y);
rectTransform.sizeDelta = gridLayoutSize;
gridLayoutSizeLast = rectTransform.sizeDelta;
// Debug.Log("rectTransform.sizeDelta--" + rectTransform.sizeDelta.y);
children.Clear();
realIndex = -1;
realIndexUp = -1;
{
info.Key.SetSiblingIndex(info.Value);
}
//children重新设置anchoredPosition;
for (int index = 0; index < transform.childCount; index++)
{
Transform child = transform.GetChild(index);
RectTransform childRectTrans = child.GetComponent<RectTransform>();
if (childsAnchoredPosition.ContainsKey(child))
{
childRectTrans.anchoredPosition = childsAnchoredPosition[child];
}
else
{
Debug.LogError("childsAnchoredPosition no contain " + child.name);
}
}
}
//获取所有child;
for (int index = 0; index < transform.childCount; index++)
{
Transform trans = transform.GetChild(index);
trans.gameObject.SetActive(true);
children.Add(transform.GetChild(index).GetComponent<RectTransform>());
//初始化前⾯⼏个;
UpdateChildrenCallback(children.Count - 1, transform.GetChild(index));
}
startPosition = rectTransform.anchoredPosition;
// Debug.Log("<Color=Red>children</Color>---"+ children.Count+ "realIndex---"+ realIndex);
realIndex = children.Count - 1;
ShowElement(realIndex);
/
/Debug.Log( ansform.));
// Debug.Log(transform.TransformPoint(children[0].localPosition));
hasInit = true;
//如果需要显⽰的个数⼩于设定的个数;
for (int index = 0; index < minAmount; index++)
{
children[index].gameObject.SetActive(index < amount);
}
if (straint == GridLayoutGroup.Constraint.FixedColumnCount)
{
//如果⼩了⼀⾏,则需要把GridLayout的⾼度减去⼀⾏的⾼度;
int row = (minAmount - amount) / straintCount;
if (row > 0)
{
rectTransform.sizeDelta -= new Vector2(0, (llSize.y + gridLayoutGroup.spacing.y) * row);
}
}
else
{
//如果⼩了⼀列,则需要把GridLayout的宽度减去⼀列的宽度;
int column = (minAmount - amount) / straintCount;
if (column > 0)
{
rectTransform.sizeDelta -= new Vector2((llSize.x + gridLayoutGroup.spacing.x) * column, 0);
}
}
//if (amount <= minAmount)
// abled = false;
//else
// abled = true;
}
void ScrollCallback(Vector2 data)
{
UpdateChildren();
}
void UpdateChildren()
{
// Debug.Log("当前位置");
if (transform.childCount < minAmount)
{
return;
}
// Debug.Log("当前位置" + rectTransform.anchoredPosition.y + "startPosition.y" + startPosition.y);
currentPos = rectTransform.anchoredPosition;
/
/Vector2 currentPos = rectTransform.anchoredPosition;
if (straint == GridLayoutGroup.Constraint.FixedColumnCount)
{
float offsetY = currentPos.y - startPosition.y;
if (offsetY > 0)
{
//向上拉,向下扩展;
{
if (realIndex >= amount - 1)
{
startPosition = currentPos;
return;
}
up = false;
float scrollRectUp = ansform.).y;
Vector3 childBottomLeft = new Vector3(children[0].anchoredPosition.x, children[0].anchoredPosition.y - gridLayoutGroup.spacing.y - llSize.y * 0.5f, 0f); //llSize.y float childBottom = transform.TransformPoint(childBottomLeft).y;
if (childBottom >= scrollRectUp)
{
Debug.Log("childBottom >= scrollRectUp");
//移动到底部;
for (int index = 0; index < straintCount; index++)
{
children[index].SetAsLastSibling();
realIndex++;
if (realIndex > amount - 1)
{
children[index].gameObject.SetActive(false);
}
else
{
UpdateChildrenCallback(realIndex, children[index]);
}
}
ShowElement(realIndex);
//GridLayoutGroup 底部加长;
rectTransform.sizeDelta += new Vector2(0, llSize.y + gridLayoutGroup.spacing.y);
gridLayoutSizeLast = rectTransform.sizeDelta;
// Debug.Log("<Color=Red>gridLayoutSizeLast.y</Color>" + gridLayoutSizeLast.y);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
}
// Debug.Log("realIndex向上--" + realIndex);
}
}
else
{
//Debug.Log("Drag Down");
//向下拉,下⾯收缩;
if (realIndex + 1 <= children.Count)
{
startPosition = currentPos;
return;
}
RectTransform scrollRectTransform = scrollRect.GetComponent<RectTransform>();
Vector3 scrollRectAnchorBottom = new Vector3(0, -height - gridLayoutGroup.spacing.y, 0f);//- gridLayoutGroup.spacing.y
float scrollRectBottom = ansform.TransformPoint(scrollRectAnchorBottom).y;
Vector3 childUpLeft = new Vector3(children[children.Count - 1].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y + gridLayoutGroup.spacing.y * minAmount, 0f);//gridLayoutGroup.spacing.y realIndex-minAmount+1 float childUp = transform.TransformPoint(childUpLeft).y;
//Debug.Log("childUp----" + childUp + "scrollRectBottom---" + scrollRectBottom);
if (childUp < scrollRectBottom)
{
//Debug.Log("childUp < scrollRectBottom");
up = true;
//把底部的⼀⾏移动到顶部
for (int index = 0; index < straintCount; index++)
{
children[children.Count - 1 - index].SetAsFirstSibling();
children[children.Count - 1 - index].anchoredPosition = new Vector2(children[children.Count - 1 - index].anchoredPosition.x, children[0].anchoredPosition.y + llSize.y + gridLayoutGroup.spacing.y);
children[children.Count - 1 - index].gameObject.SetActive(true);
UpdateChildrenCallback(realIndex - children.Count - index, children[children.Count - 1 - index]);
}
realIndex -= straintCount;
ShowElement(realIndex);
//GridLayoutGroup 底部缩短;
//rectTransform.anchoredPosition = gridLayoutPos;
rectTransform.sizeDelta -= new Vector2(0, llSize.y + gridLayoutGroup.spacing.y);
gridLayoutSizeLast = rectTransform.sizeDelta;
//Debug.Log("<Color=Red>gridLayoutSizeLast.y</Color>" + gridLayoutSizeLast.y);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
}
// Debug.Log("realIndex向下--" + realIndex);
}
}
#region 左右滑动
else
{
float offsetX = currentPos.x - startPosition.x;
if (offsetX < 0)
{
//向左拉,向右扩展;
{
if (realIndex >= amount - 1)
{
startPosition = currentPos;
return;
}
float scrollRectLeft = ansform.).x;
Vector3 childBottomRight = new Vector3(children[0].anchoredPosition.x + llSize.x, children[0].anchoredPosition.y, 0f);
float childRight = transform.TransformPoint(childBottomRight).x;
// Debug.LogError("childRight=" + childRight);
if (childRight <= scrollRectLeft)
{
//Debug.Log("childRight <= scrollRectLeft");
//移动到右边;
for (int index = 0; index < straintCount; index++)
{
children[index].SetAsLastSibling();
children[index].anchoredPosition = new Vector2(children[children.Count - 1].anchoredPosition.x + llSize.x + gridLayoutGroup.spacing.x, children[index].anchoredPosition.y);
realIndex++;
if (realIndex > amount - 1)
{
children[index].gameObject.SetActive(false);
}
{
UpdateChildrenCallback(realIndex, children[index]);
}
}
if (realIndex >= 7)
//GridLayoutGroup 右侧加长;
rectTransform.sizeDelta += new llSize.x + gridLayoutGroup.spacing.x, 0);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
}
}
}
else
{
//Debug.Log("Drag Down");
//向右拉,右边收缩;
if (realIndex + 1 <= children.Count)
{
startPosition = currentPos;
return;
}
RectTransform scrollRectTransform = scrollRect.GetComponent<RectTransform>();
Vector3 scrollRectAnchorRight = new width + gridLayoutGroup.spacing.x, 0, 0f);
float scrollRectRight = ansform.TransformPoint(scrollRectAnchorRight).x;
Vector3 childUpLeft = new Vector3(children[children.Count - 1].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y, 0f);
float childLeft = transform.TransformPoint(childUpLeft).x;
if (childLeft >= scrollRectRight)
{
//Debug.LogError("childLeft > scrollRectRight");
//把右边的⼀⾏移动到左边;
for (int index = 0; index < straintCount; index++)
{
children[children.Count - 1 - index].SetAsFirstSibling();
children[children.Count - 1 - index].anchoredPosition = new Vector2(children[0].anchoredPosition.x - llSize.x - gridLayoutGroup.spacing.x, children[children.Count - 1 - index].anchoredPosition.y); children[children.Count - 1 - index].gameObject.SetActive(true);
UpdateChildrenCallback(realIndex - children.Count - index, children[children.Count - 1 - index]);
}
//GridLayoutGroup 右侧缩短;
rectTransform.sizeDelta -= new llSize.x + gridLayoutGroup.spacing.x, 0);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
realIndex -= straintCount;
}
#endregion
}
}
// Debug.Log("realIndex--" + realIndex);
//Debug.Log("currentPos.y--" + currentPos.y + "rectTransform.sizeDelta---" + rectTransform.sizeDelta.y);
startPosition = currentPos;
gridLayoutPosLast = currentPos;
}
void UpdateChildrenCallback(int index, Transform trans)
{
if (updateChildrenCallback != null)
jquery滚动条滚动到底部{
updateChildrenCallback(index, trans);
}
}
public virtual void ShowElement(int endIndex)
{
}
/// <summary>
/// 设置总的个数;
/// </summary>
/// <param name="count"></param>
public void SetAmount(int count)
{
amount = count;
//如果切换⾯板
if (!changePanel)
{
//hasInit = false;
StartCoroutine(InitChildren());
changePanel = true;
}
else
{
/
/ Debug.Log("currentPos.y--" + currentPos.y);
if (currentPos.y > 10)
{
如果需要显⽰的个数⼩于设定的个数;
//Debug.Log("minAmount--"+minAmount);
for (int index = 0; index < minAmount; index++)
{
children[index].gameObject.SetActive(index < amount);
}
//删除操作
if (GameInstance.isDecrase)
{
if (realIndex > minAmount - 1)
{
realIndex--;
//把底部的⼀⾏移动到顶部
for (int index = 0; index < straintCount; index++)
{
children[children.Count - 1 - index].SetAsFirstSibling();
children[children.Count - 1 - index].anchoredPosition = new Vector2(children[children.Count - 1 - index].anchoredPosition.x, children[0].anchoredPosition.y + llSize.y + gridLayoutGroup.spacing.y); children[children.Count - 1 - index].gameObject.SetActive(true);
UpdateChildrenCallback(realIndex - children.Count - index, children[children.Count - 1 - index]);
}
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent<RectTransform>();
}
}
GameInstance.isDecrase = false;//GameInstance类中bool变量控制条⽬删除的刷新使⽤
currentPos = new Vector2(currentPos.x, currentPos.y - llSize.y - gridLayoutGroup.spacing.y);
if (realIndex > minAmount - 1)
{
gridLayoutSizeLast = new Vector2(gridLayoutSizeLast.x, gridLayoutSizeLast.y - llSize.y - gridLayoutGroup.spacing.y);
}
else
rectTransform.anchoredPosition = currentPos;
}
else
rectTransform.anchoredPosition = currentPos;
rectTransform.sizeDelta = gridLayoutSizeLast;
rectTransform.anchoredPosition = new Vector2(currentPos.x, currentPos.y);
startPosition = rectTransform.anchoredPosition;
ShowElement(realIndex);
}
else
{
StartCoroutine(InitChildren());
}
}
}
}
2.MarketLayoutGroup类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MarketLayoutGroup : InfinityGridLayoutGroup
{
bool isNotOutRange = false;
//商店市场的可买的商品集合
private List<MarketGood> marketGoods;
//可出售到商店的商品集合
public List<SealGood> marketSeal;
//可要在商店加⼯的商品集合
private List<ExchangeGood> marketMake;
/
/重写⽗类的调⽤循环刷新显⽰
public override void ShowElement(int endIndex)
{
//获取商店窗体对象
MarketActivity market = MainPanelContrller.Instance.presenter.MarketWindowsActivity[0] as MarketActivity;
//判断当前窗体默认开启的类型是否是可买的商品集合
if (market.current == CurrentPanel.Image_Buy)
{
//获取可买商品的数据( GameInstance全局数据储存脚本)
marketGoods = GameInstance.marketGoods;
//判断商品数
amount = marketGoods.Count;
//Debug.Log ("marketGoods--"+marketGoods.Count);
//endIndex为可见ui的最⼤下标
isNotOutRange = endIndex < marketGoods.Count ? true : false;
//遍历ui对象数⽬判断每⼀条ui应该显⽰的数据并调⽤MarketElement赋值显⽰。
for (int i = 0; i < transform.childCount; i++)
{
//获取ui显⽰对象
MarketElement presenter = transform.GetChild(i).GetComponent<MarketElement>();
//判断并且赋值显⽰
if (isNotOutRange)
{
// = myGoodList[endIndex - minAmount + 1 + i].name;
presenter.SetData(marketGoods[endIndex - minAmount + 1 + i]);
}
else
{
if (endIndex - minAmount + 1 + i < marketGoods.Count)
{
presenter.SetData(marketGoods[endIndex - minAmount + 1 + i]);
}
else
{
MarketGood good = new MarketGood();
presenter.SetData(good);
}
}
}
}
else if (market.current == CurrentPanel.Image_Seal)
{
if (GameInstance.marketSeals == null)
return;
/
/Debug.Log("GameInstance.marketSeals" + GameInstance.marketSeals.Count);
// Debug.Log("marketSeal" + marketSeal);
marketSeal = GameInstance.marketSeals;
amount = marketSeal.Count;
isNotOutRange = endIndex < marketSeal.Count ? true : false;
for (int i = 0; i < transform.childCount; i++)
{
ElementSeal presenter = transform.GetChild(i).GetComponent<ElementSeal>();
if (isNotOutRange)
{
//Debug.Log("endIndex+" + endIndex);
/
/Debug.Log(endIndex - minAmount + 1 + i);
// = myGoodList[endIndex - minAmount + 1 + i].name;
presenter.SetData(marketSeal[endIndex - minAmount + 1 + i]);
}
else
{
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论