因为业务需求需要做一个循环的列表,无限循环,
而unity自带的scrollview不满足循环的要求,所以就自定义了一个控件
控件结构如下:
下面是写的代码代码里的注释包含我的思路,以及优化方案
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
using DG.Tweening;
namespace MocoDog
{
public class pageView : UIWindowBase
{
// Start is called before the first frame update
public GameObject content;//父控件
public GameObject preItem; //cell
public GameObject btnLeft;//父控件
public GameObject btnRight;//父控件
private float posx = 0;//初始位置
private float cellSize = 0;//每次移动的距离
private float maxPosX = 0;//当前最大位置X
private float minPosX = 0;//当前最小位置
private List<GameObject> itemList;//item存储容器
void Start()
{
this.RegisterEvent(btnLeft, OnClickBtnLeft);
this.RegisterEvent(btnRight, OnClickBtnRight);
preItem.SetActive(false);
var rt = preItem.GetComponent<RectTransform>();
cellSize = rt.sizeDelta.x + 30;
Debug.Log("====cellSize: " + cellSize);
// var rt1 = content.GetComponent<RectTransform>();
// posx = rt1.anchoredPosition.x;
// Debug.Log("====rt1.posx: " + posx);
InitItemList();
}
void InitItemList()
{
itemList = new List<GameObject>();
for (int i = 0; i < 10; i++)
{
GameObject obj = GameObject.Instantiate(preItem);
obj.transform.SetParent(content.GetComponent<Transform>());
if (i == 9)
{
obj.transform.localPosition = new Vector3(cellSize * -1,-200,0);
minPosX = cellSize * -1;
}
else
{
obj.transform.localPosition = new Vector3(cellSize * i,-200,0);
maxPosX = cellSize * i;
}
obj.transform.Find("bg_count/Text").GetComponent<Text>().text = i.ToString();
obj.transform.localScale = Vector3.one;
if (!obj.activeSelf)
obj.SetActive(true);
//添加元素到数组中
itemList.Add(obj);
}
ListSort();
}
void OnClickBtnLeft(GameObject objname)
{
posx = posx - cellSize;
Debug.Log("====posx: " + posx);
content.transform.DOLocalMoveX(posx, 0.4f);
//
var obj2 = itemList[4];
ani2(obj2);
var obj1 = itemList[1];
ani1(obj1);
//移动第一个子节点到最后面
var obj = itemList[0];
maxPosX = maxPosX + cellSize;
minPosX = minPosX + cellSize;
obj.transform.localPosition = new Vector3(maxPosX,-200,0);
ListSort();
}
void OnClickBtnRight(GameObject objname)
{
posx = posx + cellSize;
Debug.Log("====posx: " + posx);
content.transform.DOLocalMoveX(posx, 0.4f);
var obj1 = itemList[3];
ani1(obj1);
var obj2 = itemList[0];
ani2(obj2);
//移动一个子节点到最前面
var obj = itemList[itemList.Count - 1];
//改变obj的位置
maxPosX = maxPosX - cellSize;
minPosX = minPosX - cellSize;
obj.transform.localPosition = new Vector3(minPosX,-200,0);
//根据位置对List排序
ListSort();
}
void ListSort()
{
itemList.Sort(
delegate(GameObject p1,GameObject p2)
{
return p1.transform.localPosition.x.CompareTo( p2.transform.localPosition.x);//升序
}
);
//做优化的话在这里将content位置归零然后遍历子节点更改位置
//可以用一个常量数组存储节点位置
//同时重置最大坐标最小坐标
//注意一定要在动作结束后执行
}
void ani1(GameObject obj)
{
RectTransform rectx = obj.GetComponent<RectTransform>();
Sequence mySequence = DOTween.Sequence();
mySequence.Append(rectx.DOScale(0.8f, 0.2f).SetEase(Ease.InSine));
// mySequence.Append(rectx.DOScale(Vector3.one, 0.1f).OnComplete(() =>
// {
// //动画完成
// }));
}
void ani2(GameObject obj)
{
RectTransform rectx = obj.GetComponent<RectTransform>();
Sequence mySequence = DOTween.Sequence();
mySequence.Append(rectx.DOScale(1.2f, 0.2f).SetEase(Ease.InSine));
mySequence.Append(rectx.DOScale(Vector3.one, 0.1f).OnComplete(() =>
{
//动画完成
}));
}
// Update is called once per frame
void Update()
{
}
}
}
不足之处,由于是不停的移动content的位置,如果用户闲得无聊一直一个方向点击时间过长的话,有可能会出现posx超界的情况,所以可以在移动结束的时候将content的位置归零,然后遍历子节点更改位置,这部分代码我就不放出来了
源码地址:pageview.unitypackage_Unity无限循环滚动列表-Unity3D文档类资源-CSDN下载