| using System.Collections;  | 
| using System.Collections.Generic;  | 
| using UnityEngine;  | 
| using EnhancedUI.EnhancedScroller;  | 
| using System;  | 
| using UnityEngine.UI;  | 
|   | 
| public enum EnhanceLockType  | 
| {  | 
|     None,  | 
|     LockHorizonRight,  | 
|     LockHorizonLeft,  | 
|     LockVerticalTop,  | 
|     LockVerticalBottom,  | 
|     KeepHorizon,  | 
|     KeepVertical,  | 
|     KeepVertical2,  | 
| }  | 
| public class ScrollerController : MonoBehaviour, IEnhancedScrollerDelegate {  | 
|   | 
|     private List<ScrollerData> _data = new List<ScrollerData>();  | 
|     public delegate void OnRefreshCellDelegate(ScrollerDataType type, CellView cell);  | 
|     public event OnRefreshCellDelegate OnRefreshCell;  | 
|   | 
|     public delegate bool OnDynamicCell(ScrollerDataType type,int index,out float height);  | 
|     public event OnDynamicCell OnGetDynamicSize;  | 
|   | 
|     public event Action OnRefreshCompleteEvent;  | 
|   | 
|     public event Action<Vector2> onValueChange;  | 
|   | 
|   | 
|     public EnhancedScrollerCellView GetCellView(EnhancedScroller scroller, int dataIndex, int cellIndex)  | 
|     {  | 
|         CellView cell = GetCellView(scroller, dataIndex);  | 
|         if (!cell.gameObject.activeSelf) cell.SetActive(true);  | 
|         cell.SetData(_data[dataIndex], _data[dataIndex].m_ScrollerType,this);  | 
|         if (_data[dataIndex].OnClick != null) {  | 
|             cell.OnClick = _data[dataIndex].OnClick;  | 
|         }  | 
|         cell.info = _data[dataIndex].info;  | 
|         if (OnRefreshCell != null) {  | 
|             OnRefreshCell(_data[dataIndex].m_ScrollerType, cell);  | 
|         }  | 
|         cell.RefreshUI();  | 
|         return cell;  | 
|     }  | 
|   | 
|     private CellView GetCellView(EnhancedScroller scroller, int dataIndex)  | 
|     {  | 
|         CellView cell = null;  | 
|         switch (_data[dataIndex].m_ScrollerType) {  | 
|             case ScrollerDataType.Header:  | 
|                 cell = scroller.GetCellView(m_CellHeaderPrefab) as CellView;  | 
|                 break;  | 
|             case ScrollerDataType.Normal:  | 
|                 cell = scroller.GetCellView(m_CellNomalPrefab) as CellView;  | 
|                 break;  | 
|             case ScrollerDataType.Tail:  | 
|                 cell = scroller.GetCellView(m_CellTailPrefab) as CellView;  | 
|                 break;  | 
|             case ScrollerDataType.Extra1:  | 
|                 cell = scroller.GetCellView(m_CellExtraPrefab1) as CellView;  | 
|                 break;  | 
|             case ScrollerDataType.Extra2:  | 
|                 cell = scroller.GetCellView(m_CellExtraPrefab2) as CellView;  | 
|                 break;  | 
|             case ScrollerDataType.Extra3:  | 
|                 cell = scroller.GetCellView(m_CellExtraPrefab3) as CellView;  | 
|                 break;  | 
|         }  | 
|         return cell;  | 
|     }  | 
|   | 
|     public float GetCellViewSize(EnhancedScroller scroller, int dataIndex)  | 
|     {  | 
|         if (OnGetDynamicSize != null) {  | 
|             float height = 0;  | 
|             if (OnGetDynamicSize(_data[dataIndex].m_ScrollerType, _data[dataIndex].index,out height)) {  | 
|                 return height;  | 
|             }  | 
|         }  | 
|         switch (_data[dataIndex].m_ScrollerType) {  | 
|             case ScrollerDataType.Header:  | 
|                 return m_CellHeaderPrefab.height;  | 
|             case ScrollerDataType.Normal:  | 
|                 return m_CellNomalPrefab.height;  | 
|             case ScrollerDataType.Tail:  | 
|                 return m_CellTailPrefab.height;  | 
|             case ScrollerDataType.Extra1:  | 
|                 return m_CellExtraPrefab1.height;  | 
|             case ScrollerDataType.Extra2:  | 
|                 return m_CellExtraPrefab2.height;  | 
|             case ScrollerDataType.Extra3:  | 
|                 return m_CellExtraPrefab3.height;  | 
|         }  | 
|         return 80;  | 
|     }  | 
|   | 
|     public void OnRefreshCellActive(CellView cell)  | 
|     {  | 
|         if (OnRefreshCell != null) {  | 
|             OnRefreshCell(cell.type, cell);  | 
|         }  | 
|     }  | 
|   | 
|     public int GetNumberOfCells(EnhancedScroller scroller)  | 
|     {  | 
|         return _data.Count;  | 
|     }  | 
|   | 
|     public EnhancedScroller m_Scorller;  | 
|     private ScrollRect m_ScrollRect;  | 
|     public ScrollRect mScrollRect {  | 
|         get {  | 
|             if (m_ScrollRect == null)  | 
|                 m_ScrollRect = m_Scorller.GetComponent<ScrollRect>();  | 
|             return m_ScrollRect;  | 
|         }  | 
|     }  | 
|     public CellView m_CellHeaderPrefab;  | 
|     public CellView m_CellNomalPrefab;  | 
|     public CellView m_CellTailPrefab;  | 
|     public CellView m_CellExtraPrefab1;  | 
|     public CellView m_CellExtraPrefab2;  | 
|     public CellView m_CellExtraPrefab3;  | 
|     public int maxCellCnt = 0;  | 
|     public bool fakeMiddleCenter = false; //是否需要假居中, 居中时当cell个数少 尺寸小于最大尺寸时 不可滑动; 只有header类型时才准确  | 
|     int jiaMiddleWithMaxSize = 0; //假居中的最大尺寸,自动设为预制体里的初始尺寸  | 
|   | 
|     public bool horizontal = false;  | 
|     public bool vertical = false;  | 
|     private bool inited = false;  | 
|     private int cacheJump = -1;  | 
|     private void Awake()  | 
|     {  | 
|         m_Scorller.Delegate = this;  | 
|         horizontal = mScrollRect.horizontal;  | 
|         vertical = mScrollRect.vertical;  | 
|   | 
|         mScrollRect.onValueChanged.AddListener(OnValueChangle);  | 
|   | 
|         inited = m_Scorller.inited;  | 
|         m_Scorller.OnFirstLoadAllEvent += OnFirstLoadAllEvent;  | 
|         if (m_Scorller.OnCompLoad == null && !m_Scorller.inited)  | 
|         {  | 
|             m_Scorller.OnCompLoad = OnCompLoad;  | 
|         }  | 
|         HideDefaultCell();  | 
|     }  | 
|   | 
|     private void OnValueChangle(Vector2 delta)  | 
|     {  | 
|         if (onValueChange != null)  | 
|         {  | 
|             onValueChange(delta);  | 
|         }  | 
|     }  | 
|   | 
|     private void OnFirstLoadAllEvent()  | 
|     {  | 
|         if (cacheJump != -1)  | 
|         {  | 
|             JumpIndex(cacheJump);  | 
|         }  | 
|     }  | 
|   | 
|     private void HideDefaultCell()  | 
|     {  | 
|         HideDefaultCell(m_CellHeaderPrefab);  | 
|         HideDefaultCell(m_CellNomalPrefab);  | 
|         HideDefaultCell(m_CellTailPrefab);  | 
|         HideDefaultCell(m_CellExtraPrefab1);  | 
|         HideDefaultCell(m_CellExtraPrefab2);  | 
|         HideDefaultCell(m_CellExtraPrefab3);  | 
|     }  | 
|   | 
|     private void HideDefaultCell(CellView _cell)  | 
|     {  | 
|         if (_cell != null)  | 
|         {  | 
|             _cell.SetActive(false);  | 
|         }  | 
|     }  | 
|   | 
|     List<CellView> list = new List<CellView>();  | 
|   | 
|     private void OnCompLoad()  | 
|     {  | 
|         inited = true;  | 
|         if (_data.Count > 0)  | 
|         {  | 
|             Restart();  | 
|         }  | 
|     }  | 
|   | 
|     public void Refresh()  | 
|     {  | 
|         inited = m_Scorller.inited;  | 
|         if (m_Scorller.OnCompLoad == null && !m_Scorller.inited)  | 
|         {  | 
|             m_Scorller.OnCompLoad = OnCompLoad;  | 
|         }  | 
|         _data.Clear();  | 
|   | 
|         if (!inited)  | 
|         {  | 
|             return;  | 
|         }  | 
|   | 
|         //假居中恢复尺寸  | 
|         if (fakeMiddleCenter && jiaMiddleWithMaxSize != 0)  | 
|         {  | 
|             var rect = (transform as RectTransform);  | 
|             if (horizontal)  | 
|             {  | 
|                 rect.sizeDelta = rect.sizeDelta.SetX(jiaMiddleWithMaxSize);  | 
|             }  | 
|             else if (vertical)  | 
|             {  | 
|                 rect.sizeDelta = rect.sizeDelta.SetY(jiaMiddleWithMaxSize);  | 
|             }  | 
|         }  | 
|   | 
|   | 
|         if (m_Scorller.LayoutGroup != null)  | 
|         {  | 
|             m_Scorller.LayoutGroup.spacing = m_Scorller.spacing;  | 
|         }  | 
|   | 
|         lastScrollPos = horizontal ? mScrollRect.horizontalNormalizedPosition : mScrollRect.verticalNormalizedPosition;  | 
|         lastContentSize = m_Scorller._ScrollSize;  | 
|   | 
|         mScrollRect.verticalNormalizedPosition = 1;  | 
|         mScrollRect.horizontalNormalizedPosition = 0;  | 
|   | 
|         lastScrollPos = Mathf.Clamp01(lastScrollPos);  | 
|   | 
|     }  | 
|   | 
|     public CellView GetActiveCellView(int _index)  | 
|     {  | 
|         if (m_Scorller == null)  | 
|         {  | 
|             return null;  | 
|         }  | 
|         var _cellView = m_Scorller.GetActiveCellView(_index);  | 
|         if (_cellView != null)  | 
|         {  | 
|             return _cellView as CellView;  | 
|         }  | 
|         return null;  | 
|     }  | 
|   | 
|     public CellView GetActiveCellView(int _index, ScrollerDataType type)  | 
|     {  | 
|         if (m_Scorller == null)  | 
|         {  | 
|             return null;  | 
|         }  | 
|         var views = m_Scorller.GetActiveCellViews();  | 
|         for (int i = 0; i < views.Count; i++)  | 
|         {  | 
|             var _cellView = views[i] as CellView;  | 
|             if (views[i].index == _index && _cellView.type == type)  | 
|             {  | 
|                 return _cellView;  | 
|             }  | 
|         }  | 
|         return null;  | 
|     }  | 
|   | 
|     public List<CellView> GetActiveCellViews()  | 
|     {  | 
|         if (m_Scorller == null)  | 
|         {  | 
|             return null;  | 
|         }  | 
|         var views = m_Scorller.GetActiveCellViews();  | 
|         List<CellView> list = new List<CellView>();  | 
|         for (int i = 0; i < views.Count; i++)  | 
|         {  | 
|             var _cellView = views[i] as CellView;  | 
|             list.Add(_cellView);  | 
|         }  | 
|         return list;  | 
|     }  | 
|   | 
|     public void AddCell(ScrollerDataType type, int index, Action<CellView> action = null, CellInfo? info = null)  | 
|     {  | 
|         ScrollerData data = null;  | 
|         switch (type) {  | 
|             case ScrollerDataType.Header:  | 
|                 data = new ScrollerHeaderData(index, action);  | 
|                 break;  | 
|             case ScrollerDataType.Normal:  | 
|                 data = new ScrollerNormalData(index, action);  | 
|                 break;  | 
|             case ScrollerDataType.Tail:  | 
|                 data = new ScrollerTailData(index, action);  | 
|                 break;  | 
|             case ScrollerDataType.Extra1:  | 
|             case ScrollerDataType.Extra2:  | 
|             case ScrollerDataType.Extra3:  | 
|                 data = new ScrollerExtraData(index, type, action);  | 
|                 break;  | 
|         }  | 
|         if (data != null) {  | 
|             data.info = info;  | 
|             _data.Add(data);  | 
|         }  | 
|     }  | 
|   | 
|     public void AddCell(ScrollerDataType type, int index, CellInfo info)  | 
|     {  | 
|         ScrollerData data = null;  | 
|         switch (type) {  | 
|             case ScrollerDataType.Header:  | 
|                 data = new ScrollerHeaderData(index);  | 
|                 break;  | 
|             case ScrollerDataType.Normal:  | 
|                 data = new ScrollerNormalData(index);  | 
|                 break;  | 
|             case ScrollerDataType.Tail:  | 
|                 data = new ScrollerTailData(index);  | 
|                 break;  | 
|             case ScrollerDataType.Extra1:  | 
|             case ScrollerDataType.Extra2:  | 
|             case ScrollerDataType.Extra3:  | 
|                 data = new ScrollerExtraData(index, type);  | 
|                 break;  | 
|         }  | 
|         if (data != null) {  | 
|             data.info = info;  | 
|             _data.Add(data);  | 
|         }  | 
|     }  | 
|   | 
|     public void OnRefreshAdd()  | 
|     {  | 
|         Restart();  | 
|     }  | 
|   | 
|     public void Restart()  | 
|     {  | 
|         if (!inited) return;  | 
|   | 
|   | 
|         m_Scorller.ReloadData();  | 
|   | 
|         if (fakeMiddleCenter && _data.Count <= maxCellCnt)  | 
|         {  | 
|             //只有设置header时,进行假居中处理才能达到效果  | 
|             if (jiaMiddleWithMaxSize == 0)  | 
|             {   | 
|                 jiaMiddleWithMaxSize = (int)m_Scorller.ScrollRectSize;  | 
|             }  | 
|   | 
|   | 
|             var rect = (transform as RectTransform);  | 
|             if (horizontal)  | 
|             {  | 
|                   | 
|                 rect.sizeDelta = rect.sizeDelta.SetX(Math.Min(jiaMiddleWithMaxSize, (m_CellHeaderPrefab.height + m_Scorller.spacing) * _data.Count - m_Scorller.spacing));  | 
|             }  | 
|             else if (vertical)  | 
|             {  | 
|                 rect.sizeDelta = rect.sizeDelta.SetY(Math.Min(jiaMiddleWithMaxSize, (m_CellHeaderPrefab.height + m_Scorller.spacing) * _data.Count - m_Scorller.spacing));  | 
|             }  | 
|             if (rect.sizeDelta.x < jiaMiddleWithMaxSize)  | 
|             {  | 
|                 mScrollRect.horizontal = false;  | 
|                 mScrollRect.vertical = false;  | 
|             }  | 
|             else  | 
|             {  | 
|                 mScrollRect.horizontal = horizontal;  | 
|                 mScrollRect.vertical = vertical;  | 
|             }  | 
|         }  | 
|         else if (maxCellCnt != 0 && _data.Count <= maxCellCnt)  | 
|         {  | 
|             mScrollRect.horizontal = false;  | 
|             mScrollRect.vertical = false;  | 
|         }  | 
|         else  | 
|         {  | 
|             mScrollRect.horizontal = horizontal;  | 
|             mScrollRect.vertical = vertical;  | 
|         }  | 
|   | 
|         ResetScrollPos();  | 
|   | 
|         lastDataCnt = _data.Count;  | 
|     }  | 
|   | 
|     public void JumpIndex(int index)  | 
|     {  | 
|         if (!inited)  | 
|         {  | 
|             cacheJump = index;  | 
|             return;  | 
|         }  | 
|         if ((index < 0 || index >= _data.Count) && !m_Scorller.Loop)  | 
|         {  | 
|             return;  | 
|         }  | 
|         var _size = m_Scorller.GetScrollPositionForDataIndex(index, EnhancedScroller.CellViewPositionEnum.Before);  | 
|         var _contentSize = vertical ? m_Scorller.scrollRect.content.rect.size.y : m_Scorller.scrollRect.content.rect.size.x;  | 
|         if (_contentSize - _size < m_Scorller.ScrollRectSize)  | 
|         {  | 
|             _size = _contentSize - m_Scorller.ScrollRectSize;  | 
|         }  | 
|         m_Scorller.ScrollPosition = _size;  | 
|     }  | 
|   | 
|     public void JumpIndex(int index,ref float offset)  | 
|     {  | 
|         if (!inited)  | 
|         {  | 
|             cacheJump = index;  | 
|             return;  | 
|         }  | 
|         if ((index < 0 || index >= _data.Count) && !m_Scorller.Loop)  | 
|         {  | 
|             return;  | 
|         }  | 
|         var _size = m_Scorller.GetScrollPositionForDataIndex(index, EnhancedScroller.CellViewPositionEnum.Before);  | 
|         var _contentSize = vertical ? m_Scorller.scrollRect.content.rect.size.y : m_Scorller.scrollRect.content.rect.size.x;  | 
|         offset = 0f;  | 
|         if (_contentSize - _size < m_Scorller.ScrollRectSize)  | 
|         {  | 
|             offset = _size - (_contentSize - m_Scorller.ScrollRectSize);  | 
|             _size = _size - offset;  | 
|         }  | 
|         m_Scorller.ScrollPosition = _size;  | 
|     }  | 
|   | 
|     public float GetCellSize(int _dataIndex)  | 
|     {  | 
|         if (!inited)  | 
|         {  | 
|             return 0;  | 
|         }  | 
|         return m_Scorller.GetCellSize(_dataIndex);  | 
|     }  | 
|   | 
|     //滑动过去  | 
|     public void MoveToIndex(int index, float _time, EnhancedScroller.TweenType _tweenType)  | 
|     {  | 
|         if (!inited)  | 
|         {  | 
|             cacheJump = index;  | 
|             return;  | 
|         }  | 
|         if ((index < 0 || index >= _data.Count) && !m_Scorller.Loop)  | 
|         {  | 
|             return;  | 
|         }  | 
|         var _size = m_Scorller.GetScrollPositionForDataIndex(index, EnhancedScroller.CellViewPositionEnum.Before);  | 
|   | 
|         m_Scorller.Tween(_tweenType, _time, _size);  | 
|     }  | 
|   | 
|   | 
|     public void JumpIndex(float _delta, float _time, EnhancedScroller.TweenType _tweenType)  | 
|     {  | 
|         if (!inited)  | 
|         {  | 
|             return;  | 
|         }  | 
|         m_Scorller.Tween(_tweenType, _time, m_Scorller.ScrollPosition + _delta);  | 
|     }  | 
|   | 
|     public float GetPreScrollSize(int index)  | 
|     {  | 
|         float _size = 0;  | 
|         for (int i = 0; i < _data.Count; i++) {  | 
|             _size += GetCellViewSize(m_Scorller, i);  | 
|             if (i >= index) break;  | 
|         }  | 
|         return _size;  | 
|     }  | 
|   | 
|     public void RefreshSingleCellView(int _index)  | 
|     {  | 
|         CellView _cell;  | 
|         if (IsDisplay(_index, out _cell))  | 
|         {  | 
|             _cell.RefreshCellView();  | 
|         }  | 
|     }  | 
|   | 
|     public bool IsDisplay(int index, out CellView _cell)  | 
|     {  | 
|         _cell = null;  | 
|         if (m_Scorller == null)  | 
|         {  | 
|             return false;  | 
|         }  | 
|         var _base = m_Scorller.GetActiveCellView(index);  | 
|         if (_base != null)  | 
|         {  | 
|             _cell = _base as CellView;  | 
|             return true;  | 
|         }  | 
|         return false;  | 
|     }  | 
|   | 
|     public bool IsDisplay(int index)  | 
|     {  | 
|         if (m_Scorller == null)  | 
|         {  | 
|             return false;  | 
|         }  | 
|         return m_Scorller.GetActiveCellView(index) != null;  | 
|     }  | 
|   | 
|     public bool OutOfStartView(int index)  | 
|     {  | 
|         float value=m_Scorller.GetScrollPositionForCellViewIndex(index, EnhancedScroller.CellViewPositionEnum.Before);  | 
|         if (value < m_Scorller.ScrollPosition) {  | 
|             return true;  | 
|         }  | 
|         return false;  | 
|     }  | 
|   | 
|     private void OnDestroy()  | 
|     {  | 
|         if (m_Scorller != null)  | 
|         {  | 
|             m_Scorller.OnFirstLoadAllEvent -= OnFirstLoadAllEvent;  | 
|         }  | 
|     }  | 
|   | 
|     public void OnRebuildComplete()  | 
|     {  | 
|         if (OnRefreshCompleteEvent != null)  | 
|         {  | 
|             OnRefreshCompleteEvent();  | 
|         }  | 
|     }  | 
|   | 
|     #region 滚动定位  | 
|   | 
|     private EnhanceLockType m_lockType = EnhanceLockType.None;  | 
|   | 
|     public EnhanceLockType lockType {  | 
|         get { return m_lockType; }  | 
|         set {  | 
|             m_lockType = value;  | 
|         }  | 
|     }  | 
|   | 
|     private float lastContentSize = 0;  | 
|   | 
|     private int lastDataCnt = 0;  | 
|   | 
|     private float lastScrollPos = 0;  | 
|   | 
|     public void ResetScrollPos()  | 
|     {  | 
|         if (_data.Count == 0 || !inited)  | 
|         {  | 
|             return;  | 
|         }  | 
|         switch (lockType) {  | 
|             case EnhanceLockType.LockHorizonRight: {  | 
|                     mScrollRect.horizontalNormalizedPosition = 1;  | 
|                 }  | 
|                 break;  | 
|             case EnhanceLockType.LockHorizonLeft: {  | 
|                     mScrollRect.horizontalNormalizedPosition = 0;  | 
|                 }  | 
|                 break;  | 
|             case EnhanceLockType.LockVerticalTop: {  | 
|                     mScrollRect.verticalNormalizedPosition = 1;  | 
|                 }  | 
|                 break;  | 
|             case EnhanceLockType.LockVerticalBottom: {  | 
|                     mScrollRect.verticalNormalizedPosition = 0;  | 
|                     m_Scorller.ScrollPosition = m_Scorller._ScrollSize;  | 
|                 }  | 
|                 break;  | 
|             case EnhanceLockType.KeepHorizon: {  | 
|                     mScrollRect.horizontalNormalizedPosition = Mathf.Clamp01(lastContentSize * lastScrollPos / m_Scorller._ScrollSize);  | 
|                 }  | 
|                 break;  | 
|             case EnhanceLockType.KeepVertical2: {  | 
|                     if(lastContentSize == m_Scorller._ScrollSize) {  | 
|                         mScrollRect.verticalNormalizedPosition = lastScrollPos;  | 
|                         m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;  | 
|                         return;  | 
|                     }  | 
|                     if (lastScrollPos == 1) {  | 
|                         mScrollRect.verticalNormalizedPosition = 1;  | 
|                     }  | 
|                     mScrollRect.verticalNormalizedPosition = Mathf.Clamp01(lastContentSize * lastScrollPos / m_Scorller._ScrollSize);  | 
|                     m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;  | 
|                 }  | 
|                 break;  | 
|             case EnhanceLockType.KeepVertical:  | 
|                 {  | 
|                     if (lastContentSize == m_Scorller._ScrollSize)  | 
|                     {  | 
|                         mScrollRect.verticalNormalizedPosition = lastScrollPos;  | 
|                         m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;  | 
|                         return;  | 
|                     }  | 
|                     if (lastScrollPos == 1)  | 
|                     {  | 
|                         mScrollRect.verticalNormalizedPosition = 1;  | 
|                     }  | 
|                     mScrollRect.verticalNormalizedPosition = Mathf.Clamp01(1 - lastContentSize * (1 - lastScrollPos) / m_Scorller._ScrollSize);  | 
|                     m_Scorller.ScrollPosition = (1 - mScrollRect.verticalNormalizedPosition) * m_Scorller._ScrollSize;  | 
|                 }  | 
|                 break;  | 
|         }  | 
|     }  | 
|   | 
|     #endregion  | 
| }  |