首先是竖直下拉,效果如下:
效果图
其中的minAmount是显示最少需要的个数,个数是整个屏幕最多能放下的个数+1 比如效果中,最多能放下三组,所以设置的是4(这里因为显示效果一行三个为1组 使用1哥prefab)
然后在 scrollRect的 connect组建中 需要使用如下组件
image.png
当前是竖向下拉 所以在GridGroupConnect中需要把 constraint 按照如下设置 在content size fitter中设置为竖向为最佳尺寸
然后是横向翻页的效果
5555.gif
image.png
connect的设置如下
需要注意的是 当时为了方便计算 在使用时需要将
image.png
prefab 进行如下设置
image.png
prefab的所有父物体(到scrollrect为止 包括scrollrect)的pivot 也要试着为0 1 这样操作是为了计算式统一通过左上角进行计算 如果有其他需求可修改计算过程中的具体代码
代码如下:
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
using System.Collections;
//lsh
public class InfinityPackgeTool : MonoBehaviour
{
public enum Axies
{
horizontal = 0,
vertical = 1
}
public int minAmount;
public ScrollRect scrollRect;
public Transform itemPrefab;
public delegate void UpdateChildrenCallBack(int index, Transform trans);
public UpdateChildrenCallBack updateChildrenDelegate = null;
private GameObject scrollContent;
private GridLayoutGroup gridLayoutGroup;
private ContentSizeFitter contentSizeFitter;
private List childTransList;
private Dictionary childStartIndexDic;
private Dictionary childStartAnchordPosition;
private Vector2 connectStartSize;
private Vector2 connectStartAnchordPos;
private int childItemNum;
private int realEndIndex = -1;
private int amount;
private RectTransform rectTransform;
private RectTransform scrollRectTrans;
private Vector2 lastPosition;
private Vector2 gridLayoutStartSize;
private Axies axies;
private bool isNeedAutoChangeConnectScale;
private bool isRegistEvent = false;
///
///
///
/// item的数量
/// 是否需要自动修改大小 若为true则直接设置为最大大小并不自动更改 否则根据当前位置自动更改connect大小
public void SetAmount(int num,bool isNeedAutoChangeScale)
{
amount = num;
isNeedAutoChangeConnectScale = isNeedAutoChangeScale;
StartCoroutine(InitManager());
}
IEnumerator InitManager()
{
if (!isRegistEvent)
{
for (int i = 0; i < minAmount; i++)
{
GameObject g = Instantiate(itemPrefab).gameObject;
g.transform.SetParent(itemPrefab.transform.parent);
g.transform.localScale = Vector3.one;
g.SetActive(true);
}
Destroy(itemPrefab.gameObject);
}
yield return 0;//wait for a flame
//first open
if (!isRegistEvent)
{
isRegistEvent = true;
scrollContent = scrollRect.content.gameObject;
rectTransform = scrollContent.GetComponent();
gridLayoutGroup = scrollContent.GetComponent();
contentSizeFitter = scrollContent.GetComponent();
connectStartSize = scrollContent.GetComponent().sizeDelta;
lastPosition = rectTransform.anchoredPosition;
gridLayoutStartSize = rectTransform.sizeDelta;
connectStartAnchordPos = rectTransform.anchoredPosition;
scrollRectTrans = scrollRect.GetComponent();
gridLayoutGroup.enabled = false;
contentSizeFitter.enabled = false;
axies = Axies.vertical;
if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedRowCount)
axies = Axies.horizontal;
childItemNum = scrollContent.transform.childCount;
childTransList = new List();
childStartIndexDic = new Dictionary();
childStartAnchordPosition = new Dictionary();
for (int index = 0; index < childItemNum; index++)
{
Transform t = scrollContent.transform.GetChild(index);
childTransList.Add(t.GetComponent());
childStartIndexDic.Add(t, index);
childStartAnchordPosition.Add(index, t.GetComponent().anchoredPosition);
}
if(!isNeedAutoChangeConnectScale)
{
int pageNum = amount / gridLayoutGroup.constraintCount + ((amount % gridLayoutGroup.constraintCount == 0) ? 0 : 1);
if (axies == Axies.horizontal)
{
scrollContent.GetComponent().sizeDelta = new Vector2(gridLayoutGroup.cellSize.x * pageNum + gridLayoutGroup.spacing.x * (pageNum - 1) + gridLayoutGroup.padding.left+gridLayoutGroup.padding.right, scrollContent.GetComponent().sizeDelta.y);
//scrollRect.horizontalNormalizedPosition = 0;
}
else
{
scrollContent.GetComponent().sizeDelta = new Vector2(scrollContent.GetComponent().sizeDelta.x, gridLayoutGroup.cellSize.y * pageNum + gridLayoutGroup.spacing.y * (pageNum - 1) + gridLayoutGroup.padding.top + gridLayoutGroup.padding.bottom);
//scrollRect.verticalNormalizedPosition = 1;
}
}
scrollRect.onValueChanged.AddListener(UpdateChildren);
}
else
{
//reset all data
if (isNeedAutoChangeConnectScale)
scrollContent.GetComponent().sizeDelta = connectStartSize;
else
{
int pageNum = amount / gridLayoutGroup.constraintCount + ((amount % gridLayoutGroup.constraintCount == 0) ? 0 : 1);
if (axies == Axies.horizontal)
{
scrollContent.GetComponent().sizeDelta = new Vector2(gridLayoutGroup.cellSize.x * pageNum + gridLayoutGroup.spacing.x * (pageNum - 1) + gridLayoutGroup.padding.left + gridLayoutGroup.padding.right, scrollContent.GetComponent().sizeDelta.y);
}
else
{
scrollContent.GetComponent().sizeDelta = new Vector2(scrollContent.GetComponent().sizeDelta.x, gridLayoutGroup.cellSize.y * pageNum + gridLayoutGroup.spacing.y * (pageNum - 1) + gridLayoutGroup.padding.top + gridLayoutGroup.padding.bottom);
}
}
scrollContent.GetComponent().anchoredPosition = connectStartAnchordPos;
childTransList.Clear();
foreach (var d in childStartIndexDic)
{
d.Key.SetSiblingIndex(d.Value);
d.Key.GetComponent().anchoredPosition = childStartAnchordPosition[d.Value];
childTransList.Add(d.Key.GetComponent());
}
}
//init data
int num = amount;
if (childItemNum < amount)
num = childItemNum;
for (int index = 0; index < childItemNum; index++)
{
if (index < amount)
{
updateChildrenDelegate(index, childTransList[index]);
childTransList[index].gameObject.SetActive(true);
}
else
{
childTransList[index].gameObject.SetActive(false);
}
}
realEndIndex = childItemNum-1;
}
public void AcheivementRemovePhotoUpdate(int pageNum)
{
//移动到目标页数
for (int index = 0; index <= pageNum; index++)
{
lastPosition.x = 0;
UpdateChildren(Vector2.zero);
}
}
private void UpdateChildren(Vector2 v)
{
if (scrollContent.transform.childCount < minAmount)
return;
Vector2 currentPos = rectTransform.anchoredPosition;
//is horizontal slide
if (axies == Axies.horizontal)
{
float offset = currentPos.x - lastPosition.x;
//connct move direct : right ,right column move to left
if (offset > 0)
{
//is slide to connect buttom,return
if (realEndIndex <= childItemNum - 1)
{
lastPosition = currentPos;
return;
}
float scrollRectRight = scrollRect.transform.TransformPoint(new Vector3(scrollRectTrans.rect.width + gridLayoutGroup.spacing.x, 0, 0)).x;
//is last item left line x pos more than scrollLeft x pos plus gridGroupLayout spacing x pos
Vector3 childLastColunmLeft = new Vector3(childTransList[childItemNum - 1].anchoredPosition.x + gridLayoutGroup.spacing.x - gridLayoutGroup.cellSize.x * childTransList[childItemNum - 1].pivot.x, 0, 0);//need to add spacing
float childLeft =scrollContent.transform.TransformPoint(childLastColunmLeft).x;
if (childLeft >= scrollRectRight)
{
//right column move to left
for (int index = 0; index ().sizeDelta -= new Vector2(gridLayoutGroup.spacing.x + gridLayoutGroup.cellSize.x, 0);
realEndIndex -= gridLayoutGroup.constraintCount;
}
}
else//connect move direct : left,left column to right
{
if (realEndIndex >= amount-1)
{
lastPosition = currentPos;
return;
}
float scrollRectLeft = scrollRect.transform.TransformPoint(Vector3.zero).x;
Vector3 childStartColumnRight = new Vector3(childTransList[0].anchoredPosition.x + gridLayoutGroup.cellSize.x * (1 - childTransList[0].pivot.x), 0f, 0f);
float childRight = scrollContent.transform.TransformPoint(childStartColumnRight).x;
if (childRight <= scrollRectLeft)
{
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
childTransList[index].anchoredPosition = new Vector2(childTransList[childItemNum - 1 - index].anchoredPosition.x + gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x, childTransList[index].anchoredPosition.y);
childTransList[index].SetAsLastSibling();
realEndIndex++;
if (realEndIndex >= amount)
{
childTransList[index].gameObject.SetActive(false);
}
else
{
updateChildrenDelegate(realEndIndex, childTransList[index]);
}
}
if (isNeedAutoChangeConnectScale)//need to minus spacing
scrollContent.GetComponent().sizeDelta += new Vector2(gridLayoutGroup.spacing.x + gridLayoutGroup.cellSize.x, 0);
}
}
}
else //same as horizontal
{
float offset = currentPos.y - lastPosition.y;
if (offset > 0)//connect mode direct : up,top row move to buttom
{
if (realEndIndex >= amount - 1)
{
lastPosition = currentPos;
return;
}
float scrollRectTop = scrollRect.transform.TransformPoint(Vector3.zero).y;
float childTopRowButtom = scrollContent.transform.TransformPoint(new Vector3(0, childTransList[0].anchoredPosition.y - gridLayoutGroup.cellSize.y * (1-childTransList[0].pivot.y) - gridLayoutGroup.spacing.y, 0)).y;
if (scrollRectTop < childTopRowButtom)
{
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
childTransList[index].transform.SetAsLastSibling();
childTransList[index].anchoredPosition = new Vector2(childTransList[index].anchoredPosition.x, childTransList[childItemNum - 1 ].anchoredPosition.y - gridLayoutGroup.spacing.y - gridLayoutGroup.cellSize.y);
realEndIndex++;
if (realEndIndex >= amount)
{
childTransList[index].gameObject.SetActive(false);
}
else
{
updateChildrenDelegate(realEndIndex, childTransList[index]);
}
}
if(isNeedAutoChangeConnectScale)
scrollContent.GetComponent().sizeDelta += new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
}
}
else//connect move direct down,buttom row move to top
{
if (realEndIndex <= childItemNum - 1)
{
lastPosition = currentPos;
return;
}
float scrollRectButtom = scrollRect.transform.TransformPoint(new Vector3(0,-scrollRectTrans.rect.height,0)).y;
float childButtomRowTop = scrollContent.transform.TransformPoint(new Vector3(0, childTransList[childItemNum - 1].anchoredPosition.y + gridLayoutGroup.cellSize.y * childTransList[childItemNum - 1].pivot.y, 0)).y;
if (childButtomRowTop <= scrollRectButtom)
{
for (int index = 0; index < gridLayoutGroup.constraintCount; index++)
{
childTransList[childItemNum - 1 - index].anchoredPosition = new Vector2(childTransList[childItemNum - 1 - index].anchoredPosition.x, childTransList[0].anchoredPosition.y + gridLayoutGroup.spacing.y + gridLayoutGroup.cellSize.y);
childTransList[childItemNum - 1 - index].SetAsFirstSibling();
childTransList[childItemNum - 1 - index].gameObject.SetActive(true);
updateChildrenDelegate(realEndIndex - childItemNum - index, childTransList[childItemNum - 1 - index]);
}
realEndIndex -= gridLayoutGroup.constraintCount;
if (isNeedAutoChangeConnectScale)
scrollContent.GetComponent().sizeDelta -= new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y);
}
}
}
lastPosition = currentPos;
//update child list
for (int index = 0; index < childItemNum; index++)
{
childTransList[index] = scrollContent.transform.GetChild(index).GetComponent();
}
}
}
更多unity2018的功能介绍请到paws3d爪爪学院查找。链接https://www.paws3d.com/learn/,也可以加入unity学习讨论群935714213
近期更有资深开发人士直播分享unity开发经验,详情请进入官网或加入QQ群了解