无限滚动是很常用的一个东西,平时设置好就没再管过, 偶尔用到的时候缺被几个小坑绊了一跤, 总结如下:
1,也是最基本的一点 数量要设置对;如下图
2.挂在脚本的物体要稍稍大于cell的数量
不然滑动的时候会出现各种恶心的状况 比如拉上去又弹回来什么的
3.写代码的时候 更要注意 几点:
void CreateHBlist(Dictionary dic)
{
Sql(_HttpType.Get, WD._url + "style/getStuffList", list =>
{
HouseYZList = list.result;
InitHouseYZList();
}, dic);
}
public List HouseYZList = new List();
int amount ;//Content下最多能容纳的格子数量
private InfinityGridLayoutGroup YZGrid;
void InitHouseYZList()
{
YZGrid = gameObject.FindDeepChild("Panel_Scroll/Panel_Grid").GetComponent();
YZGrid.SetAmount(HouseYZList.Count);
amount = HouseYZList.Count;//一定要设置这个数量!
YZGrid.updateChildrenCallback = Update_YZGrid;
}
///
/// 无限滚动列表回调
///
///
///
void Update_YZGrid(int index, Transform trans)
{
if (amount == 0) return;
index = index % amount;
RawImage raw = trans.gameObject.GetComponent();
DestroyImmediate(raw.texture, true);
zz_wd_CacheManager.ins.LoadImage(HouseYZList[index].previewUrl, tex => { raw.texture = tex; });
_3D_YZPage_Item item = trans.GetComponent<_3D_YZPage_Item>();
item.data = HouseYZList[index];
item.MyType = NowType;
}
4.如果滑动的时候卡顿 可以将最大数量多设置几个 提前加载就不会卡了
最后奉上我用的这个无限滚动的代码
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
[RequireComponent(typeof(GridLayoutGroup))]//网格布局
[RequireComponent(typeof(ContentSizeFitter))]//自适应
public class InfinityGridLayoutGroup : MonoBehaviour
{
[SerializeField]
int minAmount = 0;//实现无限滚动,需要的最少的child数量。屏幕上能看到的+一行看不到的,比如我在屏幕上能看到 2 行,每一行 2 个。则这个值为 2行*2个 + 1 行* 2个 = 6个。
RectTransform rectTransform;
GridLayoutGroup gridLayoutGroup;
ContentSizeFitter contentSizeFitter;
ScrollRect scrollRect;//滚动框
List children=new List();
Vector2 startPosition;//开始锚点位置
int amount = 0;
public delegate void UpdateChildrenCallbackDelegate(int index, Transform trans);
public UpdateChildrenCallbackDelegate updateChildrenCallback = null;
int realIndex = -1;
// int realIndexUp = -1; //从下往上;
bool hasInit = false;//是否初始化过
Vector2 gridLayoutSize;
Vector2 gridLayoutPos;
//存储Gird的锚点集合
Dictionary childsAnchoredPosition = new Dictionary();
//存储Gird的节点在所有兄弟节点中的位置<序号index,节点位置>
Dictionary childsSiblingIndex = new Dictionary();
IEnumerator InitChildren()
{
yield return 0;
///没有初始化进行初始化 并获得相应的组件设置锚点和调整锚点的大小增量
///给父体添加滚动框组件 并给滚动框添加回调点击事件
///遍历每一个孩子获取每一孩子的角标 使得每个自孩子添加锚点位置组件
///获取Gird的锚点位置以及节点
if (!hasInit)//如果没有初始化
{
//获取Grid的宽度;
rectTransform = GetComponent();
gridLayoutGroup = GetComponent();
gridLayoutGroup.enabled = false;
contentSizeFitter = GetComponent();
contentSizeFitter.enabled = false;
//锚点位置
gridLayoutPos = rectTransform.anchoredPosition;
//大小增量:矩阵变换的大小相对于锚点之间的距离。
gridLayoutSize = rectTransform.sizeDelta;
//注册ScrollRect滚动回调;
scrollRect = transform.parent.GetComponent();//给盒子的父物体添加ScrollRect滚动框组件
scrollRect.onValueChanged.AddListener((data) => { ScrollCallback(data);});
//获取所有child anchoredPosition 以及 SiblingIndex;
for (int index = 0; index < transform.childCount; index++)
{
Transform child=transform.GetChild(index);
RectTransform childRectTrans= child.GetComponent();
childsAnchoredPosition.Add(child, childRectTrans.anchoredPosition);
childsSiblingIndex.Add(child, child.GetSiblingIndex());
}
}
else
{
rectTransform.anchoredPosition = gridLayoutPos;
rectTransform.sizeDelta = gridLayoutSize;
children.Clear();
realIndex = -1;
// realIndexUp = -1;
//children重新设置上下顺序;
foreach (var info in childsSiblingIndex)
{
info.Key.SetSiblingIndex(info.Value);
}
//children重新设置anchoredPosition;
for (int index = 0; index < transform.childCount; index++)
{
Transform child = transform.GetChild(index);
RectTransform childRectTrans = child.GetComponent();
if (childsAnchoredPosition.ContainsKey(child))
{
childRectTrans.anchoredPosition = childsAnchoredPosition[child];
}
else
{
Debug.Log("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());
//children.Add(Transform.GetChild(index).GetChild(1).GetComponent);
//初始化前面几个;
UpdateChildrenCallback(children.Count - 1, transform.GetChild(index));
}
startPosition = rectTransform.anchoredPosition;
realIndex = children.Count - 1;
//Debug.Log( scrollRect.transform.TransformPoint(Vector3.zero));
// Debug.Log(transform.TransformPoint(children[0].localPosition));
hasInit = true;
//如果需要显示的个数小于设定的个数;
for (int index = 0; index < minAmount; index++)
{
children[index].gameObject.SetActive(index < amount);
//Debug.Log("第" + index + "个Gird, " + "minAmount个数为" + minAmount);
}
//如果纵向排列 设置的最小Grid数量和所需要显示的Grid数量对比结果进行锚框的高度设置
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount)
{
//如果小了一行,则需要把GridLayout的高度减去一行的高度;
int row = (minAmount - amount) / gridLayoutGroup.constraintCount;
//Debug.Log("Row的值为" + row);
if (row > 0)
{
rectTransform.sizeDelta -= new Vector2(0, (gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y) * row);
}
}
//否则横向排列 对锚框进行宽的设置
else
{
//如果小了一列,则需要把GridLayout的宽度减去一列的宽度;
int column = (minAmount - amount) / gridLayoutGroup.constraintCount;
if (column > 0)
{
rectTransform.sizeDelta -= new Vector2((gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x) * column, 0);
}
}
}
void ScrollCallback(Vector2 data)
{
UpdateChildren();
}
//刷新子物体
void UpdateChildren()
{
//如果挂有滚动框组件物体的孩子数量小于设定的最小数量
if (transform.childCount < minAmount) return;
Vector2 currentPos = rectTransform.anchoredPosition;//获取当前锚点位置
//设置滑动方向
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount)
{
float offsetY = currentPos.y - startPosition.y;//纵向滑动偏移量
if (offsetY > 0)
{
//向上拉,向下扩展;
{
if (realIndex >= amount - 1)
{
startPosition = currentPos;
return;
}
//**************************核心算法********************************//
//主要是通过获得Panel_Scroll的锚点PosY的值,这是不变的,因为开始设置的即是屏幕的高1080
//再通过他的子物体格子的PoxY,由于格子的锚点定的是居于Content的左上角,所以这里记录为childBottomLeft
//通过获得Panel_Grid.y的世界坐标Y即是Panel_Scroll的位置,此时与Panel_Scroll的恒定值1080对比
//通过对比childBottom与恒定的1080值
//当格子走过的路径大于等于1080时设置格子的层级SetAsLastSibling
//调整布局
//transform.TransformPoint 变换位置从局部坐标到世界坐标。
//获得Panel_Scroll的RectTransform PosY=1080
float scrollRectUp = scrollRect.transform.TransformPoint(Vector3.zero).y;
//纵向滑动改变的只是格子锚点的PosY
Vector3 childBottomLeft = new Vector3(children[0].anchoredPosition.x, children[0].anchoredPosition.y - gridLayoutGroup.cellSize.y, 0f);
float childBottom = transform.TransformPoint(childBottomLeft).y;
//Debug.Log("scrollRectUp====" + scrollRectUp);
//Debug.Log("childBottomLeft===" + childBottomLeft);
//Debug.Log("childBottom====" + childBottom);
if (childBottom >= scrollRectUp)
{
//Debug.Log("childBottom >= scrollRectUp");
//移动到底部;
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
children[index].SetAsLastSibling();
children[index].anchoredPosition = new Vector2(children[index].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y - gridLayoutGroup.cellSize.y - gridLayoutGroup.spacing.y);
//Debug.Log("这是格子的PosX" + children[index].anchoredPosition.x);
//Debug.Log("这是格子的PosY" + children[children.Count - 1]);
//Debug.Log("第几个啦" + gridLayoutGroup.constraintCount);
realIndex++;
if (realIndex > amount - 1)
{
children[index].gameObject.SetActive(false);
}
else
{
UpdateChildrenCallback(realIndex, children[index]);
}
}
//GridLayoutGroup 底部加长;
rectTransform.sizeDelta += new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent();
}
}
}
}
else
{
//Debug.Log("Drag Down");
//向下拉,下面收缩;
if (realIndex + 1 <= children.Count)
{
startPosition = currentPos;
return;
}
RectTransform scrollRectTransform = scrollRect.GetComponent();
Vector3 scrollRectAnchorBottom = new Vector3(0, -scrollRectTransform.rect.height - gridLayoutGroup.spacing.y, 0f);
float scrollRectBottom = scrollRect.transform.TransformPoint(scrollRectAnchorBottom).y;
Vector3 childUpLeft = new Vector3(children[children.Count - 1].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y, 0f);
float childUp = transform.TransformPoint(childUpLeft).y;
if (childUp < scrollRectBottom)
{
//Debug.Log("childUp < scrollRectBottom");
//把底部的一行 移动到顶部
for (int index = 0; index < gridLayoutGroup.constraintCount; 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 + gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
children[children.Count - 1 - index].gameObject.SetActive(true);
UpdateChildrenCallback(realIndex - children.Count - index, children[children.Count - 1 - index]);
}
realIndex -= gridLayoutGroup.constraintCount;
//GridLayoutGroup 底部缩短;
rectTransform.sizeDelta -= new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent();
}
}
}
}
else
{
float offsetX = currentPos.x - startPosition.x;
if (offsetX < 0)
{
//向左拉,向右扩展;
{
if (realIndex >= amount - 1)
{
startPosition = currentPos;
return;
}
float scrollRectLeft = scrollRect.transform.TransformPoint(Vector3.zero).x;
Vector3 childBottomRight = new Vector3(children[0].anchoredPosition.x+ gridLayoutGroup.cellSize.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 < gridLayoutGroup.constraintCount; index++)
{
children[index].SetAsLastSibling();
children[index].anchoredPosition = new Vector2(children[children.Count - 1].anchoredPosition.x + gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x, children[index].anchoredPosition.y);
realIndex++;
if (realIndex > amount - 1)
{
children[index].gameObject.SetActive(false);
}
else
{
UpdateChildrenCallback(realIndex, children[index]);
}
}
//GridLayoutGroup 右侧加长;
rectTransform.sizeDelta += new Vector2(gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x,0);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent();
}
}
}
}
else
{
//Debug.Log("Drag Down");
//向右拉,右边收缩;
if (realIndex + 1 <= children.Count)
{
startPosition = currentPos;
return;
}
RectTransform scrollRectTransform = scrollRect.GetComponent();
Vector3 scrollRectAnchorRight = new Vector3(scrollRectTransform.rect.width + gridLayoutGroup.spacing.x, 0, 0f);
float scrollRectRight = scrollRect.transform.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 < gridLayoutGroup.constraintCount; index++)
{
children[children.Count - 1 - index].SetAsFirstSibling();
children[children.Count - 1 - index].anchoredPosition = new Vector2(children[0].anchoredPosition.x - gridLayoutGroup.cellSize.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 Vector2(gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x, 0);
//更新child;
for (int index = 0; index < children.Count; index++)
{
children[index] = transform.GetChild(index).GetComponent();
}
realIndex -= gridLayoutGroup.constraintCount;
}
}
}
startPosition = currentPos;
}
void UpdateChildrenCallback(int index,Transform trans)
{
if (updateChildrenCallback != null)
{
updateChildrenCallback(index, trans);
}
}
///
/// 设置总的个数;
///
///
public void SetAmount(int count)
{
amount = count;
StartCoroutine(InitChildren());
}
}