ScrollViewExtend_无限重复循环——ScrollView(转)

//*****************************-》 基类 循环列表 《-****************************
//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 = m_Content.transform.GetChild(0).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);
            }

        }
    }
}

------------------------------------------------------------

//*****************************-》 可收展 循环列表 《-****************************
//author: Kim
//初始化:
//       Init(CallBack)   //不需要 回调Cell点击函数时用此 Init()
//       Init(CallBack, OnClickCallBack)  //需要回调 Cell点击函数时用此 Init() 
//刷新列表:
//      ShowList(数量格式: string = "5|5|6")
//回调:
//Func(GameObject = 收展按钮, GameObject = Cell, int = 收展按钮索引 Index, int = 子cell索引) 
//OnClickCell(GameObject = Cell, int = Index)    //点击Cell 

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace CircularScrollView
{
    public class ExpandCircularScrollView : UICircularScrollView
    {
        public GameObject m_ExpandButton;
        public float m_BackgroundMargin;
        public bool m_IsExpand = false;

        private float m_ExpandButtonX;
        private float m_ExpandButtonY;
        private float m_ExpandButtonWidth;
        private float m_ExpandButtonHeight;

        private Vector2 m_BackgroundOriginSize;

        //展开信息
        struct ExpandInfo
        {
            public GameObject button;
            public bool isExpand;
            public CellInfo[] cellInfos;
            public float size;
            public int cellCount;
        }
        private ExpandInfo[] m_ExpandInfos = null;

        private Dictionary<GameObject, bool> m_IsAddedListener = new Dictionary<GameObject, bool>(); //用于 判断是否重复添加 点击事件

        private new Action<GameObject, GameObject, int, int> m_FuncCallBackFunc;
        protected new Action<GameObject, GameObject, int, int> m_FuncOnClickCallBack;

        public void Init(Action<GameObject, GameObject, int, int> callBack)
        {
            Init(callBack, null);
        }

        public void Init(Action<GameObject, GameObject, int, int> callBack, Action<GameObject, GameObject, int, int> onClickCallBack, Action<int, bool, GameObject> onButtonClickCallBack)
        {
            m_FuncOnButtonClickCallBack = onButtonClickCallBack;
            Init(callBack, onClickCallBack);
        }

        public void Init(Action<GameObject, GameObject, int, int> callBack, Action<GameObject, GameObject, int, int> onClickCallBack)
        {
            base.Init(null, null);

            m_FuncCallBackFunc = callBack;

            /* Button 处理 */
            if (m_ExpandButton == null)
            {
                if (m_Content.transform.Find("Button") != null)
                {
                    m_ExpandButton = m_Content.transform.Find("Button").gameObject;
                }
            }

            if (m_ExpandButton != null)
            {
                RectTransform rectTrans = m_ExpandButton.transform.GetComponent<RectTransform>();
                m_ExpandButtonX = rectTrans.anchoredPosition.x;
                m_ExpandButtonY = rectTrans.anchoredPosition.y;

                SetPoolsButtonObj(m_ExpandButton);

                m_ExpandButtonWidth = rectTrans.rect.width;
                m_ExpandButtonHeight = rectTrans.rect.height;

                var background = m_ExpandButton.transform.Find("background");
                if (background != null)
                {
                    m_BackgroundOriginSize = background.GetComponent<RectTransform>().sizeDelta;
                }
            }
        }

        public override void ShowList(string numStr)
        {
            ClearCell(); //清除所有Cell (非首次调Showlist时执行)

            int totalCount = 0;

            int beforeCellCount = 0;

            string[] numArray = numStr.Split('|');
            int buttonCount = numArray.Length;

            bool isReset;
            if (m_IsInited && m_ExpandInfos.Length == buttonCount)
            {
                isReset = false;
            }
            else
            {
                m_ExpandInfos = new ExpandInfo[buttonCount];
                isReset = true;
            }

            for (int k = 0; k < buttonCount; k++)
            {
                //-> Button 物体处理
                GameObject button = GetPoolsButtonObj();
                button.name = k.ToString();
                Button buttonComponent = button.GetComponent<Button>();
                if (!m_IsAddedListener.ContainsKey(button) && buttonComponent != null)
                {
                    m_IsAddedListener[button] = true;
                    buttonComponent.onClick.AddListener(delegate () { OnClickExpand(button); });
                    button.transform.SetSiblingIndex(0);
                }

                float pos = 0;  //坐标( isVertical ? 记录Y : 记录X )

                //-> 计算 Button 坐标
                if (m_Direction == e_Direction.Vertical)
                {
                    pos = m_ExpandButtonHeight * k + m_Spacing * (k + 1);
                    pos += k > 0 ? (m_CellObjectHeight + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / m_Row) : 0;
                    button.transform.GetComponent<RectTransform>().anchoredPosition = new Vector3(m_ExpandButtonX, -pos, 0);
                }
                else
                {
                    pos = m_ExpandButtonWidth * k + m_Spacing * (k + 1);
                    pos += k > 0 ? (m_CellObjectWidth + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / m_Row) : 0;
                    button.transform.GetComponent<RectTransform>().anchoredPosition = new Vector3(pos, m_ExpandButtonY, 0);
                }

                int count = int.Parse(numArray[k]);
                totalCount += count;

                //-> 存储数据
                ExpandInfo expandInfo = isReset ? new ExpandInfo() : m_ExpandInfos[k];
                expandInfo.button = button;
                expandInfo.cellCount = count;
                expandInfo.cellInfos = new CellInfo[count];

                expandInfo.isExpand = isReset ? m_IsExpand : expandInfo.isExpand;
                expandInfo.size = m_Direction == e_Direction.Vertical ? (m_CellObjectHeight + m_Spacing) * Mathf.CeilToInt((float)count / m_Row) : (m_CellObjectWidth + m_Spacing) * Mathf.CeilToInt((float)count / m_Row); //计算 需展开的尺寸

                //-> 遍历每个按钮下的 Cell
                for (int i = 0; i < count; i++)
                {
                    if (!expandInfo.isExpand) break;

                    CellInfo cellInfo = new CellInfo();

                    float rowPos = 0; //计算每排里面的cell 坐标

                    //-> 计算Cell坐标
                    if (m_Direction == e_Direction.Vertical)
                    {
                        pos = m_CellObjectHeight * Mathf.CeilToInt(i / m_Row) + m_Spacing * (Mathf.CeilToInt(i / m_Row) + 1);
                        pos += (m_ExpandButtonHeight + m_Spacing) * (k + 1);
                        pos += (m_CellObjectHeight + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / 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.CeilToInt(i / m_Row) + m_Spacing * (Mathf.CeilToInt(i / m_Row) + 1);
                        pos += (m_ExpandButtonWidth + m_Spacing) * (k + 1);
                        pos += (m_CellObjectHeight + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / 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;
                        expandInfo.cellInfos[i] = cellInfo;
                        continue;
                    }

                    //-> 取或创建 Cell
                    GameObject cell = GetPoolsObj();
                    cell.transform.GetComponent<RectTransform>().anchoredPosition = cellInfo.pos;
                    cell.gameObject.name = k + "-" + i.ToString();

                    Button cellButtonComponent = cell.GetComponent<Button>();
                    if (!m_IsAddedListener.ContainsKey(cell) && cellButtonComponent != null)
                    {
                        m_IsAddedListener[cell] = true;
                        cellButtonComponent.onClick.AddListener(delegate () { OnClickCell(cell); });
                    }

                    //-> 存数据
                    cellInfo.obj = cell;
                    expandInfo.cellInfos[i] = cellInfo;

                    //-> 回调  函数
                    Func(m_FuncCallBackFunc, button, cell, expandInfo.isExpand);
                }

                beforeCellCount += expandInfo.isExpand ? count : 0;

                m_ExpandInfos[k] = expandInfo;

                Func(m_FuncCallBackFunc, button, null, expandInfo.isExpand);
            }

            if (!m_IsInited)
            {
                //-> 计算 Content 尺寸
                if (m_Direction == e_Direction.Vertical)
                {
                    float contentSize = m_IsExpand ? (m_Spacing + m_CellObjectHeight) * Mathf.CeilToInt((float)totalCount / m_Row) : 0;
                    contentSize += (m_Spacing + m_ExpandButtonHeight) * buttonCount;
                    m_ContentRectTrans.sizeDelta = new Vector2(m_ContentRectTrans.sizeDelta.x, contentSize);
                }
                else
                {
                    float contentSize = m_IsExpand ? (m_Spacing + m_CellObjectWidth) * Mathf.CeilToInt((float)totalCount / m_Row) : 0;
                    contentSize += (m_Spacing + m_ExpandButtonWidth) * buttonCount;
                    m_ContentRectTrans.sizeDelta = new Vector2(contentSize, m_ContentRectTrans.sizeDelta.y);
                }
            }

            m_IsInited = true;
        }

        //清除所有Cell (扔到对象池)
        private void ClearCell()
        {
            if (!m_IsInited) return;

            for (int i = 0, length = m_ExpandInfos.Length; i < length; i++)
            {

                if (m_ExpandInfos[i].button != null)
                {
                    SetPoolsButtonObj(m_ExpandInfos[i].button);
                    m_ExpandInfos[i].button = null;
                }
                for (int j = 0, count = m_ExpandInfos[i].cellInfos.Length; j < count; j++)
                    if (m_ExpandInfos[i].cellInfos[j].obj != null)
                    {
                        SetPoolsObj(m_ExpandInfos[i].cellInfos[j].obj);
                        m_ExpandInfos[i].cellInfos[j].obj = null;
                    }
            }
        }

        //Cell 点击事件
        public override void OnClickCell(GameObject cell)
        {
            int index = int.Parse(((cell.name).Split('-'))[0]);
            Func(m_FuncOnClickCallBack, m_ExpandInfos[index].button, cell, m_ExpandInfos[index].isExpand);
        }

        //收展按钮 点击事件
        private void OnClickExpand(GameObject button)
        {
            int index = int.Parse(button.name) + 1;
            OnClickExpand(index);
            if (m_FuncOnButtonClickCallBack != null)
            {
                m_FuncOnButtonClickCallBack(index, m_ExpandInfos[index - 1].isExpand, button);
            }
        }
        public override void OnClickExpand(int index)
        {
            index = index - 1;
            m_ExpandInfos[index].isExpand = !m_ExpandInfos[index].isExpand;

            //-> 计算 Contant Size
            Vector2 size = m_ContentRectTrans.sizeDelta;
            if (m_Direction == e_Direction.Vertical)
            {
                float height = m_ExpandInfos[index].isExpand ? size.y + m_ExpandInfos[index].size : size.y - m_ExpandInfos[index].size;
                m_ContentRectTrans.sizeDelta = new Vector2(size.x, height);
            }
            else
            {
                float width = m_ExpandInfos[index].isExpand ? size.x + m_ExpandInfos[index].size : size.x - m_ExpandInfos[index].size;
                m_ContentRectTrans.sizeDelta = new Vector2(width, size.y);
            }

            int beforeCellCount = 0;
            float pos = 0;
            float rowPos = 0;

            //-> 重新计算坐标 并 显示处理
            for (int k = 0, length = m_ExpandInfos.Length; k < length; k++)
            {
                int count = m_ExpandInfos[k].cellCount;

                if (k >= index)
                {
                    //-> 计算 按钮位置
                    GameObject button = m_ExpandInfos[k].button;
                    if (m_Direction == e_Direction.Vertical)
                    {
                        pos = m_ExpandButtonHeight * k + m_Spacing * (k + 1);
                        pos += (m_CellObjectHeight + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / m_Row);
                        button.transform.GetComponent<RectTransform>().anchoredPosition = new Vector3(m_ExpandButtonX, -pos, 0);
                    }
                    else
                    {
                        pos = m_ExpandButtonWidth * k + m_Spacing * (k + 1);
                        pos += (m_CellObjectWidth + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / m_Row);
                        button.transform.GetComponent<RectTransform>().anchoredPosition = new Vector3(pos, m_ExpandButtonY, 0);
                    }

                    ExpandInfo expandInfo = m_ExpandInfos[k];
                    for (int i = 0; i < count; i++)
                    {
                        //-> 按钮 收 状态时
                        if (!expandInfo.isExpand)
                        {
                            if (expandInfo.cellInfos[i].obj != null)
                            {
                                SetPoolsObj(expandInfo.cellInfos[i].obj);
                                m_ExpandInfos[k].cellInfos[i].obj = null;
                            }
                            continue;
                        }

                        CellInfo cellInfo = expandInfo.cellInfos[i];

                        // * -> 计算每个Cell坐标
                        if (m_Direction == e_Direction.Vertical)
                        {
                            pos = m_CellObjectHeight * Mathf.FloorToInt(i / m_Row) + m_Spacing * (Mathf.FloorToInt(i / m_Row) + 1);
                            pos += (m_ExpandButtonHeight + m_Spacing) * (k + 1);
                            pos += (m_CellObjectHeight + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / 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) + 1);
                            pos += (m_ExpandButtonWidth + m_Spacing) * (k + 1);
                            pos += (m_CellObjectWidth + m_Spacing) * Mathf.CeilToInt((float)beforeCellCount / 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))
                        {
                            SetPoolsObj(cellInfo.obj);
                            cellInfo.obj = null;
                            m_ExpandInfos[k].cellInfos[i] = cellInfo;
                            continue;
                        }

                        GameObject cell = cellInfo.obj != null ? cellInfo.obj : GetPoolsObj();
                        cell.transform.GetComponent<RectTransform>().anchoredPosition = cellInfo.pos;
                        cell.gameObject.name = k + "-" + i.ToString();

                        //-> 回调
                        if (cellInfo.obj == null)
                        {
                            Func(m_FuncCallBackFunc, button, cell, expandInfo.isExpand);
                        }

                        //-> 添加按钮事件
                        Button cellButtonComponent = cell.GetComponent<Button>();
                        if (!m_IsAddedListener.ContainsKey(cell) && cellButtonComponent != null)
                        {
                            m_IsAddedListener[cell] = true;
                            cellButtonComponent.onClick.AddListener(delegate () { OnClickCell(cell); });
                        }

                        //-> 存数据
                        cellInfo.obj = cell;
                        m_ExpandInfos[k].cellInfos[i] = cellInfo;
                    }
                }

                if (m_ExpandInfos[k].isExpand)
                {
                    //beforeCellCount += count;

                    /// <summary>
                    /// 修改 2020.10.25
                    /// </summary>
                    /// <param name="2"> 2 为列数 </param>
                    beforeCellCount += Mathf.CeilToInt((float)count / 2) * 2;
                }
            }

            //展开时候的背景图
            ExpandBackground(m_ExpandInfos[index]);
            Func(m_FuncCallBackFunc, m_ExpandInfos[index].button, null, m_ExpandInfos[index].isExpand);
        }

        //展开时候的背景图
        private void ExpandBackground(ExpandInfo expandInfo)
        {
            //收展时的 list尺寸变化
            if (expandInfo.isExpand == false)
            {
                var background = expandInfo.button.transform.Find("background");
                if (background != null)
                {
                    RectTransform backgroundTransform = background.GetComponent<RectTransform>();
                    backgroundTransform.sizeDelta = m_BackgroundOriginSize;
                }
            }
            else
            {
                var background = expandInfo.button.transform.Find("background");
                if (background != null)
                {
                    RectTransform backgroundTransform = background.GetComponent<RectTransform>();
                    float total_h = expandInfo.size;
                    if (m_Direction == e_Direction.Vertical)
                    {
                        if (total_h > 3)
                        {
                            backgroundTransform.sizeDelta = new Vector2(m_BackgroundOriginSize.x, m_BackgroundOriginSize.y + total_h + m_BackgroundMargin);
                        }
                        else
                        {
                            backgroundTransform.sizeDelta = new Vector2(m_BackgroundOriginSize.x, m_BackgroundOriginSize.y);
                        }
                    }
                    else
                    {
                        backgroundTransform.sizeDelta = new Vector2(m_BackgroundOriginSize.x + total_h + m_BackgroundMargin, m_BackgroundOriginSize.y);
                    }
                }
            }
        }

        protected override void ScrollRectListener(Vector2 value)
        {
            Vector3 contentP = m_ContentRectTrans.anchoredPosition;

            if (m_ExpandInfos == null) return;

            for (int k = 0, length = m_ExpandInfos.Length; k < length; k++)
            {
                ExpandInfo expandInfo = m_ExpandInfos[k];
                if (!expandInfo.isExpand)
                {
                    continue;
                }

                int count = expandInfo.cellCount;
                for (int i = 0; i < count; i++)
                {
                    CellInfo cellInfo = expandInfo.cellInfos[i];
                    float rangePos = m_Direction == e_Direction.Vertical ? cellInfo.pos.y : cellInfo.pos.x;
                    if (IsOutRange(rangePos))
                    {
                        SetPoolsObj(cellInfo.obj);
                        m_ExpandInfos[k].cellInfos[i].obj = null;
                    }
                    else
                    {
                        if (cellInfo.obj == null)
                        {
                            GameObject cell = GetPoolsObj();
                            cell.transform.GetComponent<RectTransform>().anchoredPosition = cellInfo.pos;
                            cell.name = k + "-" + i;

                            Button cellButtonComponent = cell.GetComponent<Button>();
                            if (!m_IsAddedListener.ContainsKey(cell) && cellButtonComponent != null)
                            {
                                m_IsAddedListener[cell] = true;
                                cellButtonComponent.onClick.AddListener(delegate () { OnClickCell(cell); });
                            }

                            cellInfo.obj = cell;

                            m_ExpandInfos[k].cellInfos[i] = cellInfo;

                            Func(m_FuncCallBackFunc, expandInfo.button, cell, expandInfo.isExpand);
                        }
                    }
                }
            }
        }

        private Stack<GameObject> buttonPoolsObj = new Stack<GameObject>();
        //取出 button
        private GameObject GetPoolsButtonObj()
        {
            GameObject button = null;
            if (buttonPoolsObj.Count > 0)
            {
                button = buttonPoolsObj.Pop();
            }
            if (button == null)
            {
                button = Instantiate(m_ExpandButton) as GameObject;
            }
            button.transform.SetParent(m_Content.transform);
            button.transform.localScale = Vector3.one;
            UIUtils.SetActive(button, true);

            return button;
        }
        //存入 button
        private void SetPoolsButtonObj(GameObject button)
        {
            if (button != null)
            {
                buttonPoolsObj.Push(button);
                UIUtils.SetActive(button, false);
            }
        }

        private void Func(Action<GameObject, GameObject, int, int> Func, GameObject button, GameObject selectObject, bool isShow)
        {
            string[] objName = { "1", "-2" };
            if (selectObject != null)
            {
                objName = (selectObject.name).Split('-');
            }
            int buttonNum = int.Parse(button.name) + 1;
            int num = int.Parse(objName[1]) + 1;

            if (Func != null)
            {
                if (selectObject != null)
                {
                    //Func(button, selectObject, buttonNum, num, isShow);
                    Func(button, selectObject, buttonNum, num);

                }
                else
                {
                    //Func(button, selectObject, buttonNum, -1, isShow);
                    Func(button, selectObject, buttonNum, -1);

                }
            }
        }

    }
}

-----------------------------------------------------------

//*****************************-》 展开Tips 循环列表 《-****************************
//author: Kim
//初始化:
//      Init(CallBack, OnClickCallBack)
//刷新列表:
//      ShowList(int = 数量)
//回调:
// 1: Func(cell, index)  //列表刷新回调
// 2: OnClickCell(cell, index) 点击Cell 回调

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace CircularScrollView
{
    public class ExpandTipsCircularScrollView : UICircularScrollView
    {
        public GameObject m_ExpandTips;
        public GameObject m_Arrow;
        public float m_TipsSpacing;

        private float m_ExpandTipsHeight;
        private bool m_IsExpand = false;

        public override void Init(Action<GameObject, int> callBack, Action<GameObject, int> onClickCallBack)
        {
            base.Init(callBack, onClickCallBack);

            //m_ExpandTips.SetActive(false);
            UIUtils.SetActive(m_ExpandTips, false);

            var rectTrans = m_ExpandTips.GetComponent<RectTransform>();
            rectTrans.pivot = new Vector2(0, 1);
            rectTrans.anchorMin = new Vector2(0, 1);
            rectTrans.anchorMax = new Vector2(0, 1);
            rectTrans.anchoredPosition = new Vector2(0, 0);
            rectTrans.sizeDelta = new Vector2(m_ContentWidth, rectTrans.sizeDelta.y);

            m_ExpandTipsHeight = m_ExpandTips.GetComponent<RectTransform>().rect.height;

           if( m_Arrow != null)
            {
                var arrowRectTrams = m_Arrow.GetComponent<RectTransform>();
                arrowRectTrams.pivot = new Vector2(0.5f, 0.5f);
                arrowRectTrams.anchorMin = new Vector2(0, 0.5f);
                arrowRectTrams.anchorMax = new Vector2(0, 0.5f);
            }
        }

        public override void ShowList(int num)
        {
            base.ShowList(num);

            m_IsExpand = false;
            m_IsClearList = true;
            lastClickCellName = null;
            UIUtils.SetActive(m_ExpandTips, false);
            //m_ExpandTips.SetActive(false);
        }

        private string lastClickCellName = null;
        public override void OnClickCell(GameObject cell)
        {
            if(lastClickCellName == null || cell.name == lastClickCellName || !m_IsExpand)
            {
                m_IsExpand = !m_IsExpand;
            }
            lastClickCellName = cell.name;

            float index = float.Parse(cell.name);

            int curRow = Mathf.FloorToInt(index / m_Row) + 1;

            //-> Tips框 显示
            //m_ExpandTips.SetActive(m_IsExpand);
            UIUtils.SetActive(m_ExpandTips, m_IsExpand);
            m_ExpandTips.transform.localPosition = new Vector3(0, -((m_Spacing + m_CellObjectHeight) * curRow + m_TipsSpacing), 0);

            //-> Content尺寸 计算
            float contentHeight = m_IsExpand ? m_ContentHeight + m_ExpandTipsHeight + m_TipsSpacing : m_ContentHeight;
            contentHeight = contentHeight < m_PlaneHeight ? m_PlaneHeight : contentHeight;
            m_ContentRectTrans.sizeDelta = new Vector2(m_ContentWidth, contentHeight);

            m_MinIndex = -1;

            for(int i = 0, length = m_CellInfos.Length ; i < length; i++)
            {
                CellInfo cellInfo = m_CellInfos[i];

                float pos = 0;  // Y 坐标
                float rowPos = 0; //计算每排里面的cell 坐标

                pos = m_CellObjectHeight * Mathf.FloorToInt(i / m_Row) + m_Spacing * (Mathf.FloorToInt(i / m_Row) + 1);
                rowPos = m_CellObjectWidth * (i % m_Row) + m_Spacing * (i % m_Row);

                pos += (i/m_Row >= curRow && m_IsExpand) ? m_ExpandTipsHeight + m_TipsSpacing*2 - m_Spacing : 0; //往下移 Tips框高 和 距离

                cellInfo.pos = new Vector3(rowPos, -pos, 0);

                if(IsOutRange(-pos))
                {
                    if(cellInfo.obj != null)
                    {
                        SetPoolsObj(cellInfo.obj);
                        cellInfo.obj = null;
                    }
                }
                else
                {
                    //-> 记录显示范围中的 首位index 和 末尾index
                    m_MinIndex = m_MinIndex == -1 ? i : m_MinIndex;// 首位 Index
                    m_MaxIndex = i; // 末尾 Index

                    GameObject cellObj = cellInfo.obj == null ? GetPoolsObj() : cellInfo.obj;
                    cellObj.GetComponent<RectTransform>().anchoredPosition = cellInfo.pos;
                    cellInfo.obj = cellObj;
                }

                m_CellInfos[i] = cellInfo;
            }

            if (m_Arrow != null)
            {
                var arrowObj = m_Arrow.transform.GetComponent<RectTransform>();
                arrowObj.anchoredPosition = new Vector2(cell.transform.localPosition.x + (m_CellObjectWidth / 2), arrowObj.anchoredPosition.y);
            }
            Func(m_FuncOnClickCallBack, cell);
        }

        private Dictionary<GameObject, bool> isAddedListener = new Dictionary<GameObject, bool>();
        protected override GameObject GetPoolsObj()
        {
            GameObject cell = base.GetPoolsObj();

            if (!isAddedListener.ContainsKey(cell))
            {
                Button button = cell.GetComponent<Button>() == null ? cell.AddComponent<Button>() : cell.GetComponent<Button>();

                button.onClick.AddListener(delegate () { OnClickCell(cell); });

                isAddedListener[cell] = true;
            }

            return cell;
        }
    }
}

------------------------------------------

//*****************************-》 滑动翻页 循环列表 《-****************************
//author: Kim
//初始化:
//      Init(CallBack)
//      Init(CallBack, SlidePageCallBack)   SlidePageCallBack = 返回当前页的回调
//刷新列表:
//      ShowList(int = 数量)
//回调:
// 1: Func(cell, index)  //列表刷新回调
// 2: SlidePageFunc( int = pageIndex ) 翻页回调 param = 当前页

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace CircularScrollView
{
    public class FlipPageCircularScrollView : UICircularScrollView
    {
        public int m_OnePageCount = 1;      //每页显示的项目
        public float m_SlideSpeed = 5;       //滑动速度

        public bool m_IsMaxRange = false;

        // * -> 是否开启 导航图标模式
        public bool m_IsOpenNavIcon = false;

        //-> 开启 导航图标模式时 使用以下变量
        public float m_IconSize = 20;
        public float m_IconSpacing = 5.0f;
        public Sprite m_SelectIcon = null;
        public Sprite m_NormalIcon = null;
        public Transform m_ObjNavigation;
        // <-

        private int m_AllPageCount;           //总页数
        private int m_NowIndex = 0;          //当前位置索引
        private int m_LastIndex = -1;        //上一次的索引
        private bool m_IsDrag = false;          //是否拖拽中
        private float m_TargetPos = 0;              //滑动的目标位置  
        private List<float> m_ListPageValue = new List<float> { 0 };  //总页数索引比列 0-1  

        private List<Image> m_NavigationList = new List<Image>();

        protected new Action<int> m_FuncOnClickCallBack;

        public override void ShowList(int num)
        {
            base.ShowList(num);
            ListPageValueInit();
        }

        //翻页到某一页
        public override void SetToPageIndex(int index)
        {
            m_IsDrag = false;
            m_NowIndex = index - 1;
            m_TargetPos = m_ListPageValue[m_NowIndex];

            for (int i = 0; i < m_NavigationList.Count; i++)
            {
                if (i == m_NowIndex)
                {
                    m_NavigationList[m_NowIndex].sprite = m_SelectIcon;
                }
                else
                {
                    m_NavigationList[i].sprite = m_NormalIcon;
                }
            }
            if (m_FuncOnClickCallBack != null)
            {
                Func(m_FuncOnClickCallBack, m_NowIndex);
            }
        }

        //每页比例  
        void ListPageValueInit()
        {
            m_NavigationList.Clear();
            m_AllPageCount = m_MaxCount - m_OnePageCount;
            if (m_MaxCount != 0)
            {
                for (float i = 1; i <= m_AllPageCount; i++)
                {
                    m_ListPageValue.Add((i / m_AllPageCount));
                }
            }
            if (m_IsOpenNavIcon && m_MaxCount > 1)
            {
                if (m_ObjNavigation == null)
                {
                    m_ObjNavigation = transform.Find("m_ObjNavigation");
                }
                float[] posArray = new float[m_MaxCount];
                if (m_MaxCount == 1)
                {
                    posArray[0] = 0;
                }
                else
                {
                    float startX = -m_MaxCount / 2 * m_IconSpacing;
                    for (int i = 0; i < m_MaxCount; i++)
                    {
                        posArray[i] = startX + m_IconSpacing * i;
                    }
                }

                for (int i = 0; i < m_MaxCount; i++)
                {
                    GameObject icon = null;
                    if (m_ObjNavigation.Find(string.Format("icon{0}", i)) != null)
                    {
                        icon = m_ObjNavigation.Find(string.Format("icon{0}", i)).gameObject;
                    }
                    else
                    {
                        icon = new GameObject(string.Format("icon{0}", i));
                    }
                    icon.transform.parent = m_ObjNavigation;
                    Image img = null;
                    if (icon.GetComponent<Image>() == null)
                    {
                        img = icon.AddComponent<Image>();
                    }
                    else
                    {
                        img = icon.GetComponent<Image>();
                    }
                    if (i == 0)
                    {
                        img.sprite = m_SelectIcon;
                    }
                    else
                    {
                        img.sprite = m_NormalIcon;
                    }
                    img.rectTransform.sizeDelta = new Vector2(m_IconSize, m_IconSize);
                    icon.transform.localScale = Vector3.one;
                    icon.transform.localPosition = new Vector3(posArray[i], 0, 0);
                    m_NavigationList.Add(img);
                }
            }
            if (m_FuncOnClickCallBack != null)
            {
                Func(m_FuncOnClickCallBack, m_NowIndex);
            }
        }

        void Update()
        {
                if (!m_IsDrag)
                {
                    if (m_ScrollRect == null) return;

                    if(m_Direction == e_Direction.Vertical)
                    {
                        m_ScrollRect.verticalNormalizedPosition = Mathf.Lerp(m_ScrollRect.verticalNormalizedPosition, m_TargetPos, Time.deltaTime * m_SlideSpeed);
                    }
                    else
                    {
                        m_ScrollRect.horizontalNormalizedPosition = Mathf.Lerp(m_ScrollRect.horizontalNormalizedPosition, m_TargetPos, Time.deltaTime * m_SlideSpeed);
                    }
                }
        }
        /// 拖动开始   
        public override void OnBeginDrag(PointerEventData eventData)
        {
            base.OnBeginDrag(eventData);
            m_IsDrag = true;
        }

        /// 拖拽结束   
        public override void OnEndDrag(PointerEventData eventData)
        {
            base.OnEndDrag(eventData);
            m_IsDrag = false;
            if (m_ListPageValue.Count == 1)
            {
                return;
            }
            float tempPos = 0;
            if(m_Direction == e_Direction.Vertical)
            {
                tempPos = m_ScrollRect.verticalNormalizedPosition;
            }
            else
            {
                tempPos = m_ScrollRect.horizontalNormalizedPosition;
            }

            if (m_IsMaxRange)
            {
                //获取拖动的值  
                var index = 0;
                float offset = Mathf.Abs(m_ListPageValue[index] - tempPos);    //拖动的绝对值  
                for (int i = 1; i < m_ListPageValue.Count; i++)
                {
                    float temp = Mathf.Abs(tempPos - m_ListPageValue[i]);
                    if (temp < offset)
                    {
                        index = i;
                        offset = temp;
                    }
                }
                m_TargetPos = m_ListPageValue[index];
                m_NowIndex = index;
                if (m_NowIndex != m_LastIndex && m_FuncOnClickCallBack != null)
                {
                    Func(m_FuncOnClickCallBack, m_NowIndex);
                }
                m_LastIndex = m_NowIndex;
            }
            else
            {
                float currPos = m_ListPageValue[m_NowIndex];
                if (tempPos > currPos)
                {
                    m_NowIndex++;
                }
                else if (tempPos < currPos)
                {
                    m_NowIndex--;
                }
                if (m_NowIndex < 0)
                {
                    m_NowIndex = 0;
                }
                if (m_NowIndex > m_ListPageValue.Count - 1)
                {
                    m_NowIndex = m_ListPageValue.Count - 1;
                }
                m_TargetPos = m_ListPageValue[m_NowIndex];

                if (m_NowIndex != m_LastIndex && m_FuncOnClickCallBack != null)
                {
                    Func(m_FuncOnClickCallBack, m_NowIndex);
                }
                m_LastIndex = m_NowIndex;
            }

            if (m_IsOpenNavIcon)
            {
                int length = m_NavigationList.Count;
                for (int i = 0; i < length; i++)
                {
                    Image img = m_NavigationList[i];
                    if (i == m_NowIndex)
                    {
                        img.sprite = m_SelectIcon;
                    }
                    else
                    {
                        img.sprite = m_NormalIcon;
                    }
                }
            }
        }

        //翻页时的回调
        private void Func(Action<int> Func, int index)
        {
            if (Func == null)
                return;

            Func(index + 1);
        }
    }
}

 

引用原文:忘记了 = = !

推荐参考:https://blog.csdn.net/flj135792468/article/details/120265718

     https://blog.csdn.net/weixin_43109909/article/details/120254614

posted on 2022-11-08 15:11  嗜睡的熊大  阅读(83)  评论(0编辑  收藏  举报

导航