水平或垂直可选
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UIScrollRect : MonoBehaviour
{
[Header("水平")]
public bool Horizontal;
[Header("垂直")]
public bool Vertical;
[Header("列数,行数")]
public Vector2 Grid; //行列数
[Header("单元格宽高")]
public Vector2 CellSize; //单元格宽高
[Header("单元格间隔")]
public Vector2 Spacing; //间隔
[Header("父物体")]
public RectTransform m_ItemParentTrans; //父物体
[Header("预制体")]
public GameObject m_Prefab; //预制体
private int RowNum; //行数
private int ColumnNum; //列数
private int m_CreateCount; //显示创建数
private int m_TotalCount; //Content显示总数量
private int m_ShowCount; //实际显示数量
private int m_LastStartIndex = 0; //上次初始序号
private int m_StartIndex = 0; //初始序号
private int m_EndIndex = 0; //结束序号
private ScrollRect m_ScrollRect; //滑动组件
private RectTransform m_SelfRectTrans;
private Dictionary<int, Transform> m_ItemIndexDic = new Dictionary<int, Transform>(); //Item对应得序号
private List<int> m_NewIndexList = new List<int>();
private List<int> m_ChangeIndexList = new List<int>();
int[] intlist = { 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219
,220,221,222,223,224,225,226,227,228,229,230,231,232,233};
void Start()
{
Init(intlist.Length);
m_ScrollRect = GetComponent<ScrollRect>();
if (m_ScrollRect != null)
{
m_ScrollRect.onValueChanged.AddListener(OnScrollRectChange);
m_ScrollRect.horizontal = Horizontal;
m_ScrollRect.vertical = Vertical;
}
m_SelfRectTrans = GetComponent<RectTransform>();
//SetCorner();
}
//private void SetCorner()
//{
// if (Vertical)
// {
// float x = (ColumnNum * CellSize.x + (ColumnNum - 1) * Spacing.x);
// Debug.Log(m_ItemParentTrans.localPosition.x);
// Debug.Log((m_ItemParentTrans.parent.localPosition.x + x));
// m_ItemParentTrans.localPosition = new Vector3(-(m_ItemParentTrans.parent.localPosition.x + x), m_ItemParentTrans.localPosition.y,0);
// }
//}
/// <summary>
/// 初始化并构建
/// </summary>
/// <param name="totalCount"></param>
public void Init(int totalCount)
{
ColumnNum = (int)Grid.x;
RowNum = (int)Grid.y;
if (ColumnNum <= 0 || RowNum <= 0)
return;
//预留三行或三列
if (ColumnNum >= RowNum)
ColumnNum += 3;
else
RowNum += 3;
m_CreateCount = ColumnNum * RowNum;
m_TotalCount = totalCount;
m_ShowCount = Mathf.Min(m_TotalCount, m_CreateCount);
int RectWidth, RectHeight;
GetContentRect(out RectWidth,out RectHeight);
m_ItemParentTrans.sizeDelta = new Vector2(RectWidth,RectHeight);
for (int index = 0; index < m_ShowCount; ++index)
{
Transform transform = GetItemTransform(index);
SetItemTransform(transform,index);
}
ShowOrHideItem(m_ItemParentTrans, m_ShowCount);
}
/// <summary>
/// 获取Content宽高
/// </summary>
public void GetContentRect(out int RectWidth,out int RectHeight)
{
if (Horizontal)
{
RectHeight = (int)(RowNum * CellSize.y + (RowNum - 1) * Spacing.y);
ColumnNum = m_TotalCount / RowNum + (m_TotalCount % RowNum > 0 ? 1 : 0); //计算有多少行,用于计算出总高度
RectWidth = (int)Mathf.Max(0, ColumnNum * CellSize.x + (ColumnNum - 1) * Spacing.x);
}
else if (Vertical)
{
RectWidth = (int)(ColumnNum * CellSize.x + (ColumnNum - 1) * Spacing.x); //计算横向列宽
RowNum = m_TotalCount / ColumnNum + (m_TotalCount % ColumnNum > 0 ? 1 : 0);
RectHeight = (int)Mathf.Max(0, RowNum * CellSize.y + (RowNum - 1) * Spacing.y); //计算行数及Content的高度
}
else
{
RectWidth = 0;
RectHeight = 0;
}
}
/// <summary>
/// 获取Item
/// 有即复用,无则创建
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
private Transform GetItemTransform(int index)
{
Transform transform = null;
//回滚(已有,复用)
if(index < m_ItemParentTrans.childCount)
{
transform = m_ItemParentTrans.GetChild(index);
}
else
{
transform = Instantiate(m_Prefab).transform;
}
transform.name = index.ToString();
transform.SetParent(m_ItemParentTrans);
transform.localScale = Vector3.one;
return transform;
}
/// <summary>
/// 赋值Item
/// </summary>
/// <param name="transform"></param>
/// <param name="index"></param>
public void SetItemTransform(Transform transform, int index)
{
if (m_ItemIndexDic.ContainsKey(index))
m_ItemIndexDic[index] = transform;
else
m_ItemIndexDic.Add(index, transform);
transform.localPosition = GetItemPos(index);
//更新属性
transform.name = "Item_"+ intlist[index];
transform.GetComponentInChildren<Text>().text = intlist[index].ToString();
}
/// <summary>
/// 获取Item位置
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
private Vector2 GetItemPos(int index)
{
if(Horizontal)
return new Vector2(index / RowNum * (CellSize.y + Spacing.x), -index % RowNum * (CellSize.x + Spacing.y));
else if(Vertical)
return new Vector2(index % ColumnNum * (Spacing.x + CellSize.x) ,-index / ColumnNum*(Spacing.y + CellSize.y));
return Vector2.zero;
}
/// <summary>
/// Item显隐
/// </summary>
/// <param name="parent"></param>
/// <param name="count"></param>
private void ShowOrHideItem(Transform parent,int count)
{
if (parent.childCount < count)
return;
for (int index = 0; index < count; index++)
{
if(index < count)
{
parent.GetChild(index).gameObject.SetActive(true);
}
else
{
parent.GetChild(index).gameObject.SetActive(false);
}
}
}
/// <summary>
/// 检测滑动
/// </summary>
/// <param name="Pos"></param>
private void OnScrollRectChange(Vector2 Pos)
{
if(m_TotalCount < m_CreateCount)
return;
m_StartIndex = GetStartIndex();
if(m_StartIndex + m_CreateCount >= m_TotalCount)
{
m_StartIndex = m_TotalCount - m_CreateCount;
m_EndIndex = m_TotalCount - 1;
}
else
{
m_EndIndex = m_StartIndex + m_CreateCount - 1;
}
if (m_StartIndex == m_LastStartIndex)
return;
m_LastStartIndex = m_StartIndex;
m_NewIndexList.Clear();
m_ChangeIndexList.Clear();
for(int index = m_StartIndex;index <= m_EndIndex; ++index)
{
m_NewIndexList.Add(index);
}
foreach (var item in m_ItemIndexDic)
{
if(item.Key >= m_StartIndex && item.Key <= m_EndIndex)
{
if(m_NewIndexList.Contains(item.Key))
{
m_NewIndexList.Remove(item.Key);
}
}
else
{
m_ChangeIndexList.Add(item.Key);
}
}
for (int index = 0; index < m_NewIndexList.Count && index < m_ChangeIndexList.Count; index++)
{
int oldIndex = m_ChangeIndexList[index];
int newIndex = m_NewIndexList[index];
if(newIndex >= 0 && newIndex < m_TotalCount)
{
Transform transform = m_ItemIndexDic[oldIndex];
m_ItemIndexDic.Remove(oldIndex);
SetItemTransform(transform, newIndex);
}
}
}
/// <summary>
/// 获取起始下标
/// </summary>
/// <returns></returns>
private int GetStartIndex()
{
if (Horizontal)
{
float x = -m_ItemParentTrans.localPosition.x;//将负坐标转正
if (x <= CellSize.x)
return 0;
float scrollWidth = m_SelfRectTrans.sizeDelta.x;
if (x >= (m_ItemParentTrans.sizeDelta.x - scrollWidth)) //拉到底部了
{
if (m_TotalCount <= m_CreateCount)
return 0;
else
return m_TotalCount - m_CreateCount;
}
return (int)((x / (CellSize.x + Spacing.x)) + (x % (CellSize.x + Spacing.x) > 0 ? 1 : 0) - 1) * RowNum;
}
else if(Vertical)
{
float y = m_ItemParentTrans.localPosition.y;
if (y <= CellSize.y)
return 0;
float scrollHeight = m_SelfRectTrans.sizeDelta.y;
Debug.Log(m_ItemParentTrans.sizeDelta.y - scrollHeight);
if (y >= (m_ItemParentTrans.sizeDelta.y - scrollHeight))
{
//显示全部了
if (m_TotalCount <= m_CreateCount)
return 0;
else
{
//未显示结束
return m_TotalCount - m_CreateCount;
}
}
return (int)((y / (CellSize.y + Spacing.y)) + (y % (CellSize.y + Spacing.y) > 0 ? 1 : 0) - 1) * ColumnNum;
}
return 0;
}
}