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 _data = new List(); 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 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(); 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 list = new List(); 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 GetActiveCellViews() { if (m_Scorller == null) { return null; } var views = m_Scorller.GetActiveCellViews(); List list = new List(); 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 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 }