123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572 |
- //*****************************-》 基类 循环列表 《-****************************
- //author kim
- //初始化:
- // Init(callBackFunc)
- //刷新整个列表(首次调用和数量变化时调用):
- // ShowList(int = 数量)
- //刷新单个项:
- // UpdateCell(int = 索引)
- //刷新列表数据(无数量变化时调用):
- // UpdateList()
- //回调:
- //Func(GameObject = Cell, int = Index) //刷新列表
- using UnityEngine;
- using UnityEngine.UI;
- using System.Collections.Generic;
- using System.Collections;
- using UnityEngine.EventSystems;
- using System;
- namespace CircularScrollView
- {
- public class UIUtils
- {
- public static void SetActive(GameObject obj, bool isActive)
- {
- if (obj != null)
- {
- obj.SetActive(isActive);
- }
- }
- }
- public enum e_Direction
- {
- Horizontal,
- Vertical
- }
- public class UICircularScrollView : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
- {
- public GameObject m_PointingFirstArrow;
- public GameObject m_PointingEndArrow;
- public e_Direction m_Direction = e_Direction.Horizontal;
- public bool m_IsShowArrow = true;
- public int m_Row = 1;
- public float m_Spacing = 0f; //间距
- public GameObject m_CellGameObject; //指定的cell
- protected Action<GameObject, int> m_FuncCallBackFunc;
- protected Action<GameObject, int> m_FuncOnClickCallBack;
- protected Action<int, bool, GameObject> m_FuncOnButtonClickCallBack;
- protected RectTransform rectTrans;
- protected float m_PlaneWidth;
- protected float m_PlaneHeight;
- protected float m_ContentWidth;
- protected float m_ContentHeight;
- protected float m_CellObjectWidth;
- protected float m_CellObjectHeight;
- protected GameObject m_Content;
- protected RectTransform m_ContentRectTrans;
- private bool m_isInited = false;
- //记录 物体的坐标 和 物体
- protected struct CellInfo
- {
- public Vector3 pos;
- public GameObject obj;
- };
- protected CellInfo[] m_CellInfos;
- protected bool m_IsInited = false;
- protected ScrollRect m_ScrollRect;
- protected int m_MaxCount = -1; //列表数量
- protected int m_MinIndex = -1;
- protected int m_MaxIndex = -1;
- protected bool m_IsClearList = false; //是否清空列表
- public virtual void Init(Action<GameObject, int> callBack)
- {
- Init(callBack, null);
- }
- public virtual void Init(Action<GameObject, int> callBack, Action<GameObject, int> onClickCallBack, Action<int, bool, GameObject> onButtonClickCallBack)
- {
- if (onButtonClickCallBack != null)
- {
- m_FuncOnButtonClickCallBack = onButtonClickCallBack;
- }
- Init(callBack, onClickCallBack);
- }
- public virtual void Init(Action<GameObject, int> callBack, Action<GameObject, int> onClickCallBack)
- {
- DisposeAll();
- m_FuncCallBackFunc = callBack;
- if (onClickCallBack != null)
- {
- m_FuncOnClickCallBack = onClickCallBack;
- }
- if (m_isInited)
- return;
- m_Content = this.GetComponent<ScrollRect>().content.gameObject;
- if (m_CellGameObject == null)
- {
- m_CellGameObject = GameObject.Instantiate(Resources.Load("FY/Prefabs/Item/Cell"))as GameObject;
- }
- /* Cell 处理 */
- //m_CellGameObject.transform.SetParent(m_Content.transform.parent, false);
- SetPoolsObj(m_CellGameObject);
- RectTransform cellRectTrans = m_CellGameObject.GetComponent<RectTransform>();
- cellRectTrans.pivot = new Vector2(0f, 1f);
- CheckAnchor(cellRectTrans);
- cellRectTrans.anchoredPosition = Vector2.zero;
- //记录 Cell 信息
- m_CellObjectHeight = cellRectTrans.rect.height;
- m_CellObjectWidth = cellRectTrans.rect.width;
- //记录 Plane 信息
- rectTrans = GetComponent<RectTransform>();
- Rect planeRect = rectTrans.rect;
- m_PlaneHeight = planeRect.height;
- m_PlaneWidth = planeRect.width;
- //记录 Content 信息
- m_ContentRectTrans = m_Content.GetComponent<RectTransform>();
- Rect contentRect = m_ContentRectTrans.rect;
- m_ContentHeight = contentRect.height;
- m_ContentWidth = contentRect.width;
- m_ContentRectTrans.pivot = new Vector2(0f, 1f);
- //m_ContentRectTrans.sizeDelta = new Vector2 (planeRect.width, planeRect.height);
- //m_ContentRectTrans.anchoredPosition = Vector2.zero;
- CheckAnchor(m_ContentRectTrans);
- m_ScrollRect = this.GetComponent<ScrollRect>();
- m_ScrollRect.onValueChanged.RemoveAllListeners();
- //添加滑动事件
- m_ScrollRect.onValueChanged.AddListener(delegate (Vector2 value) { ScrollRectListener(value); });
- if (m_PointingFirstArrow != null || m_PointingEndArrow != null)
- {
- m_ScrollRect.onValueChanged.AddListener(delegate (Vector2 value) { OnDragListener(value); });
- OnDragListener(Vector2.zero);
- }
- //InitScrollBarGameObject(); // 废弃
- m_isInited = true;
- }
- //检查 Anchor 是否正确
- private void CheckAnchor(RectTransform rectTrans)
- {
- if (m_Direction == e_Direction.Vertical)
- {
- if (!((rectTrans.anchorMin == new Vector2(0, 1) && rectTrans.anchorMax == new Vector2(0, 1)) ||
- (rectTrans.anchorMin == new Vector2(0, 1) && rectTrans.anchorMax == new Vector2(1, 1))))
- {
- rectTrans.anchorMin = new Vector2(0, 1);
- rectTrans.anchorMax = new Vector2(1, 1);
- }
- }
- else
- {
- if (!((rectTrans.anchorMin == new Vector2(0, 1) && rectTrans.anchorMax == new Vector2(0, 1)) ||
- (rectTrans.anchorMin == new Vector2(0, 0) && rectTrans.anchorMax == new Vector2(0, 1))))
- {
- rectTrans.anchorMin = new Vector2(0, 0);
- rectTrans.anchorMax = new Vector2(0, 1);
- }
- }
- }
- //实时刷新列表时用
- public virtual void UpdateList()
- {
- for (int i = 0, length = m_CellInfos.Length; i < length; i++)
- {
- CellInfo cellInfo = m_CellInfos[i];
- if (cellInfo.obj != null)
- {
- float rangePos = m_Direction == e_Direction.Vertical ? cellInfo.pos.y : cellInfo.pos.x;
- if (!IsOutRange(rangePos))
- {
- Func(m_FuncCallBackFunc, cellInfo.obj, true);
- }
- }
- }
- }
- //刷新某一项
- public void UpdateCell(int index)
- {
- CellInfo cellInfo = m_CellInfos[index - 1];
- if (cellInfo.obj != null)
- {
- float rangePos = m_Direction == e_Direction.Vertical ? cellInfo.pos.y : cellInfo.pos.x;
- if (!IsOutRange(rangePos))
- {
- Func(m_FuncCallBackFunc, cellInfo.obj);
- }
- }
- }
- public virtual void ShowList(string numStr) { }
- public virtual void ShowList(int num)
- {
- m_MinIndex = -1;
- m_MaxIndex = -1;
- //-> 计算 Content 尺寸
- if (m_Direction == e_Direction.Vertical)
- {
- float contentSize = (m_Spacing + m_CellObjectHeight) * Mathf.CeilToInt((float)num / m_Row);
- m_ContentHeight = contentSize;
- m_ContentWidth = m_ContentRectTrans.sizeDelta.x;
- contentSize = contentSize < rectTrans.rect.height ? rectTrans.rect.height : contentSize;
- m_ContentRectTrans.sizeDelta = new Vector2(m_ContentWidth, contentSize);
- if (num != m_MaxCount)
- {
- m_ContentRectTrans.anchoredPosition = new Vector2(m_ContentRectTrans.anchoredPosition.x, 0);
- }
- }
- else
- {
- float contentSize = (m_Spacing + m_CellObjectWidth) * Mathf.CeilToInt((float)num / m_Row);
- m_ContentWidth = contentSize;
- m_ContentHeight = m_ContentRectTrans.sizeDelta.x;
- contentSize = contentSize < rectTrans.rect.width ? rectTrans.rect.width : contentSize;
- m_ContentRectTrans.sizeDelta = new Vector2(contentSize, m_ContentHeight);
- if (num != m_MaxCount)
- {
- m_ContentRectTrans.anchoredPosition = new Vector2(0, m_ContentRectTrans.anchoredPosition.y);
- }
- }
- //-> 计算 开始索引
- int lastEndIndex = 0;
- //-> 过多的物体 扔到对象池 ( 首次调 ShowList函数时 则无效 )
- if (m_IsInited)
- {
- lastEndIndex = num - m_MaxCount > 0 ? m_MaxCount : num;
- lastEndIndex = m_IsClearList ? 0 : lastEndIndex;
- int count = m_IsClearList ? m_CellInfos.Length : m_MaxCount;
- for (int i = lastEndIndex; i < count; i++)
- {
- if (m_CellInfos[i].obj != null)
- {
- SetPoolsObj(m_CellInfos[i].obj);
- m_CellInfos[i].obj = null;
- }
- }
- }
- //-> 以下四行代码 在for循环所用
- CellInfo[] tempCellInfos = m_CellInfos;
- m_CellInfos = new CellInfo[num];
- //-> 1: 计算 每个Cell坐标并存储 2: 显示范围内的 Cell
- for (int i = 0; i < num; i++)
- {
- // * -> 存储 已有的数据 ( 首次调 ShowList函数时 则无效 )
- if (m_MaxCount != -1 && i < lastEndIndex)
- {
- CellInfo tempCellInfo = tempCellInfos[i];
- //-> 计算是否超出范围
- float rPos = m_Direction == e_Direction.Vertical ? tempCellInfo.pos.y : tempCellInfo.pos.x;
- if (!IsOutRange(rPos))
- {
- //-> 记录显示范围中的 首位index 和 末尾index
- m_MinIndex = m_MinIndex == -1 ? i : m_MinIndex; //首位index
- m_MaxIndex = i; // 末尾index
- if (tempCellInfo.obj == null)
- {
- tempCellInfo.obj = GetPoolsObj();
- }
- tempCellInfo.obj.transform.GetComponent<RectTransform>().anchoredPosition = tempCellInfo.pos;
- tempCellInfo.obj.name = i.ToString();
- tempCellInfo.obj.SetActive(true);
- Func(m_FuncCallBackFunc, tempCellInfo.obj);
- }
- else
- {
- SetPoolsObj(tempCellInfo.obj);
- tempCellInfo.obj = null;
- }
- m_CellInfos[i] = tempCellInfo;
- continue;
- }
- CellInfo cellInfo = new CellInfo();
- float pos = 0; //坐标( isVertical ? 记录Y : 记录X )
- float rowPos = 0; //计算每排里面的cell 坐标
- // * -> 计算每个Cell坐标
- if (m_Direction == e_Direction.Vertical)
- {
- pos = m_CellObjectHeight * Mathf.FloorToInt(i / m_Row) + m_Spacing * Mathf.FloorToInt(i / m_Row);
- rowPos = m_CellObjectWidth * (i % m_Row) + m_Spacing * (i % m_Row);
- cellInfo.pos = new Vector3(rowPos, -pos, 0);
- }
- else
- {
- pos = m_CellObjectWidth * Mathf.FloorToInt(i / m_Row) + m_Spacing * Mathf.FloorToInt(i / m_Row);
- rowPos = m_CellObjectHeight * (i % m_Row) + m_Spacing * (i % m_Row);
- cellInfo.pos = new Vector3(pos, -rowPos, 0);
- }
- //-> 计算是否超出范围
- float cellPos = m_Direction == e_Direction.Vertical ? cellInfo.pos.y : cellInfo.pos.x;
- if (IsOutRange(cellPos))
- {
- cellInfo.obj = null;
- m_CellInfos[i] = cellInfo;
- continue;
- }
- //-> 记录显示范围中的 首位index 和 末尾index
- m_MinIndex = m_MinIndex == -1 ? i : m_MinIndex; //首位index
- m_MaxIndex = i; // 末尾index
- //-> 取或创建 Cell
- GameObject cell = GetPoolsObj();
- cell.transform.GetComponent<RectTransform>().anchoredPosition = cellInfo.pos;
- cell.gameObject.name = i.ToString();
- //-> 存数据
- cellInfo.obj = cell;
- m_CellInfos[i] = cellInfo;
- //-> 回调 函数
- Func(m_FuncCallBackFunc, cell);
- }
- m_MaxCount = num;
- m_IsInited = true;
- OnDragListener(Vector2.zero);
- }
- // 更新滚动区域的大小
- public void UpdateSize()
- {
- Rect rect = GetComponent<RectTransform>().rect;
- m_PlaneHeight = rect.height;
- m_PlaneWidth = rect.width;
- }
- //滑动事件
- protected virtual void ScrollRectListener(Vector2 value)
- {
- UpdateCheck();
- }
- private void UpdateCheck()
- {
- if (m_CellInfos == null)
- return;
- //检查超出范围
- for (int i = 0, length = m_CellInfos.Length; i < length; i++)
- {
- CellInfo cellInfo = m_CellInfos[i];
- GameObject obj = cellInfo.obj;
- Vector3 pos = cellInfo.pos;
- float rangePos = m_Direction == e_Direction.Vertical ? pos.y : pos.x;
- //判断是否超出显示范围
- if (IsOutRange(rangePos))
- {
- //把超出范围的cell 扔进 poolsObj里
- if (obj != null)
- {
- SetPoolsObj(obj);
- m_CellInfos[i].obj = null;
- }
- }
- else
- {
- if (obj == null)
- {
- //优先从 poolsObj中 取出 (poolsObj为空则返回 实例化的cell)
- GameObject cell = GetPoolsObj();
- cell.transform.localPosition = pos;
- cell.gameObject.name = i.ToString();
- m_CellInfos[i].obj = cell;
- Func(m_FuncCallBackFunc, cell);
- }
- }
- }
- }
- //判断是否超出显示范围
- protected bool IsOutRange(float pos)
- {
- Vector3 listP = m_ContentRectTrans.anchoredPosition;
- if (m_Direction == e_Direction.Vertical)
- {
- if (pos + listP.y > m_CellObjectHeight || pos + listP.y < -rectTrans.rect.height)
- {
- return true;
- }
- }
- else
- {
- if (pos + listP.x < -m_CellObjectWidth || pos + listP.x > rectTrans.rect.width)
- {
- return true;
- }
- }
- return false;
- }
- //对象池 机制 (存入, 取出) cell
- protected Stack<GameObject> poolsObj = new Stack<GameObject>();
- //取出 cell
- protected virtual GameObject GetPoolsObj()
- {
- GameObject cell = null;
- if (poolsObj.Count > 0)
- {
- cell = poolsObj.Pop();
- }
- if (cell == null)
- {
- cell = Instantiate(m_CellGameObject) as GameObject;
- }
- cell.transform.SetParent(m_Content.transform);
- cell.transform.localScale = Vector3.one;
- UIUtils.SetActive(cell, true);
- return cell;
- }
- //存入 cell
- protected virtual void SetPoolsObj(GameObject cell)
- {
- if (cell != null)
- {
- poolsObj.Push(cell);
- UIUtils.SetActive(cell, false);
- }
- }
- //回调
- protected void Func(Action<GameObject, int> func, GameObject selectObject, bool isUpdate = false)
- {
- int num = int.Parse(selectObject.name) + 1;
- if (func != null)
- {
- func(selectObject, num);
- }
- }
- public void DisposeAll()
- {
- if (m_FuncCallBackFunc != null)
- {
- m_FuncCallBackFunc = null;
- }
- if (m_FuncOnClickCallBack != null)
- {
- m_FuncOnClickCallBack = null;
- }
- }
- protected void OnDestroy()
- {
- DisposeAll();
- }
- public virtual void OnClickCell(GameObject cell) { }
- //-> ExpandCircularScrollView 函数
- public virtual void OnClickExpand(int index) { }
- //-> FlipCircularScrollView 函数
- public virtual void SetToPageIndex(int index) { }
- public virtual void OnBeginDrag(PointerEventData eventData)
- {
- }
- public void OnDrag(PointerEventData eventData)
- {
- }
- public virtual void OnEndDrag(PointerEventData eventData)
- {
- }
- protected void OnDragListener(Vector2 value)
- {
- float normalizedPos = m_Direction == e_Direction.Vertical ? m_ScrollRect.verticalNormalizedPosition : m_ScrollRect.horizontalNormalizedPosition;
- if (m_Direction == e_Direction.Vertical)
- {
- if (m_ContentHeight - rectTrans.rect.height < 10)
- {
- UIUtils.SetActive(m_PointingFirstArrow, false);
- UIUtils.SetActive(m_PointingEndArrow, false);
- return;
- }
- }
- else
- {
- if (m_ContentWidth - rectTrans.rect.width < 10)
- {
- UIUtils.SetActive(m_PointingFirstArrow, false);
- UIUtils.SetActive(m_PointingEndArrow, false);
- return;
- }
- }
- if (normalizedPos >= 0.9)
- {
- UIUtils.SetActive(m_PointingFirstArrow, false);
- UIUtils.SetActive(m_PointingEndArrow, true);
- }
- else if (normalizedPos <= 0.1)
- {
- UIUtils.SetActive(m_PointingFirstArrow, true);
- UIUtils.SetActive(m_PointingEndArrow, false);
- }
- else
- {
- UIUtils.SetActive(m_PointingFirstArrow, true);
- UIUtils.SetActive(m_PointingEndArrow, true);
- }
- }
- }
- }
|